Merge remote-tracking branch 'origin/dev_New' into dev_New
# Conflicts:
# src/views/equipmentManagement/repair/index.vue
# vite.config.js
已添加63个文件
已重命名2个文件
已修改118个文件
已删除14个文件
| | |
| | | "TEST": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "ä¸å°ä¼ä¸æ°åå转åäºçº§å¥é¤å
", |
| | | "VITE_BASE_API": "http://114.132.189.42:9036", |
| | | "VITE_JAVA_API": "http://114.132.189.42:9037" |
| | | "VITE_BASE_API": "http://1.15.17.182:9003", |
| | | "VITE_JAVA_API": "http://1.15.17.182:9002" |
| | | }, |
| | | "screen": "screen/HYSNView.png", |
| | | "logo": "logo/ZGLTLogo.png", |
| | | "favicon": "favicon/favicon.ico" |
| | | }, |
| | | "LC": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "ä¸å°ä¼ä¸æ°åå转åäºçº§å¥é¤å
", |
| | | "VITE_BASE_API": "http://114.132.189.42:9036", |
| | | "VITE_JAVA_API": "http://114.132.189.42:9037" |
| | | }, |
| | | "screen": "screen/HYSNView.png", |
| | | "logo": "logo/LCLogo.png", |
| | | "favicon": "favicon/favicon.ico" |
| | | }, |
| | | "WDSY": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "ä¼å¾·å®ä¸ä¿¡æ¯ç®¡çç³»ç»", |
| | | "VITE_BASE_API": "http://114.132.189.42:8068", |
| | | "VITE_JAVA_API": "http://114.132.189.42:8085" |
| | | }, |
| | | "screen": "screen/WDSYView.png", |
| | | "logo": "logo/WDSYLogo.png", |
| | | "favicon": "favicon/WDSYico.ico" |
| | | }, |
| | | "JZYJ": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "åºæºæ²¹äºä¿¡æ¯ç®¡çç³»ç»", |
| | | "VITE_BASE_API": "http://114.132.189.42:8078", |
| | | "VITE_JAVA_API": "http://114.132.189.42:8086" |
| | | }, |
| | | "screen": "screen/JZYJView.png", |
| | | "logo": "logo/JZYJLogo.png", |
| | | "favicon": "favicon/JZYJico.ico" |
| | | }, |
| | | "ZQHX": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "ä¸å¼ºæå
´ä¿¡æ¯ç®¡çç³»ç»", |
| | | "VITE_BASE_API": "http://114.132.189.42:1234", |
| | | "VITE_JAVA_API": "http://114.132.189.42:8080" |
| | | }, |
| | | "screen": "screen/ZQHXView.png", |
| | | "logo": "logo/ZQHXLogo.png", |
| | | "favicon": "favicon/ZQHXico.ico" |
| | | }, |
| | | "XYHB": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "宣屹ç¯ä¿ä¿¡æ¯ç®¡çç³»ç»", |
| | | "VITE_BASE_API": "http://114.132.189.42:9052", |
| | | "VITE_JAVA_API": "http://114.132.189.42:9051" |
| | | }, |
| | | "screen": "screen/XYHBView.png", |
| | | "logo": "logo/XYHBLogo.png", |
| | | "favicon": "favicon/XYHBico.ico" |
| | | }, |
| | | "BHMY": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "åå®ç
¤ä¸ä¿¡æ¯ç®¡çç³»ç»", |
| | | "VITE_BASE_API": "http://114.132.189.42:9070", |
| | | "VITE_JAVA_API": "http://114.132.189.42:9069" |
| | | }, |
| | | "screen": "screen/ZQHXView.png", |
| | | "logo": "logo/BHMYLogo.png", |
| | | "favicon": "favicon/BHMY.ico" |
| | | }, |
| | | "HHKJ": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "ææç§æä¿¡æ¯ç®¡çç³»ç»", |
| | | "VITE_BASE_API": "http://114.132.189.42:9046", |
| | | "VITE_JAVA_API": "http://114.132.189.42:9047" |
| | | }, |
| | | "screen": "screen/HHKJView.png", |
| | | "logo": "logo/HHKJLogo.png", |
| | | "favicon": "favicon/HHKJIco.ico" |
| | | }, |
| | | "RZNY": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "éæ©è½æºä¿¡æ¯ç®¡çç³»ç»", |
| | | "VITE_BASE_API": "http://114.132.189.42:9058", |
| | | "VITE_JAVA_API": "http://114.132.189.42:9057" |
| | | }, |
| | | "screen": "screen/RZNYView.png", |
| | | "logo": "logo/RZNYLogo.png", |
| | | "favicon": "favicon/RZNY.ico" |
| | | }, |
| | | "TJXM": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "æ³°æ±æ´ç
¤ä¿¡æ¯ç®¡çç³»ç»", |
| | | "VITE_BASE_API": "http://114.132.189.42:9064", |
| | | "VITE_JAVA_API": "http://114.132.189.42:9063" |
| | | }, |
| | | "screen": "screen/TJXMView.png", |
| | | "logo": "logo/TJXMLogo.png", |
| | | "favicon": "favicon/TJXM.ico" |
| | | }, |
| | | "HYSN": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "å¼ä¹æ°´æ³¥ä¿¡æ¯ç®¡çç³»ç»", |
| | | "VITE_BASE_API": "http://114.132.189.42:9034", |
| | | "VITE_JAVA_API": "http://114.132.189.42:9035" |
| | | }, |
| | | "screen": "screen/HYSNView.png", |
| | | "logo": "logo/HYSNLogo.png", |
| | | "favicon": "favicon/HYSNico.ico" |
| | | }, |
| | | "JYHJ": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "éé¹°é»éä¿¡æ¯ç®¡çç³»ç»", |
| | | "VITE_BASE_API": "http://114.132.189.42:9030", |
| | | "VITE_JAVA_API": "http://114.132.189.42:9031" |
| | | }, |
| | | "screen": "screen/HYSNView.png", |
| | | "logo": "logo/JYHJLogo.png", |
| | | "favicon": "favicon/JYHJico.ico" |
| | | }, |
| | | "DHDC": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "æ¦ç
é¼è¯ä¿¡æ¯ç®¡çç³»ç»", |
| | | "VITE_BASE_API": "http://114.132.189.42:9032", |
| | | "VITE_JAVA_API": "http://114.132.189.42:9033" |
| | | }, |
| | | "screen": "screen/DHDCView.png", |
| | | "logo": "logo/DHDCLogo.png", |
| | | "favicon": "favicon/DHDCico.ico" |
| | | }, |
| | | "MXSC": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "é½å
´ç³æä¿¡æ¯ç®¡çç³»ç»", |
| | | "VITE_BASE_API": "http://114.132.189.42:9048", |
| | | "VITE_JAVA_API": "http://114.132.189.42:9049" |
| | | }, |
| | | "screen": "screen/MXSCBack.png", |
| | | "logo": "logo/MXSCLogo.png", |
| | | "favicon": "favicon/MXSCIco.ico" |
| | | }, |
| | | "CJNY": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "åå·¨è½æºä¿¡æ¯ç®¡çç³»ç»", |
| | | "VITE_BASE_API": "http://114.132.189.42:9038", |
| | | "VITE_JAVA_API": "http://114.132.189.42:9039" |
| | | }, |
| | | "screen": "screen/MXSCBack.png", |
| | | "logo": "logo/CJNYLogo.png", |
| | | "favicon": "favicon/CJNYico.ico" |
| | | }, |
| | | "JSMY": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "éç³ç
¤ä¸ä¿¡æ¯ç®¡çç³»ç»", |
| | | "VITE_BASE_API": "http://114.132.189.42:9042", |
| | | "VITE_JAVA_API": "http://114.132.189.42:9043" |
| | | }, |
| | | "screen": "screen/MXSCBack.png", |
| | | "logo": "logo/JSMYLogo.png", |
| | | "favicon": "favicon/JSMYico.ico" |
| | | }, |
| | | "JSYNY": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "é¦çæºè½æºä¿¡æ¯ç®¡çç³»ç»", |
| | | "VITE_BASE_API": "http://114.132.189.42:9074", |
| | | "VITE_JAVA_API": "http://114.132.189.42:9073" |
| | | }, |
| | | "screen": "screen/HYSNView.png", |
| | | "logo": "logo/JSYNYLogo.png", |
| | | "favicon": "favicon/JSYNYico.ico" |
| | | }, |
| | | "CMNY": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "åéè½æºä¿¡æ¯ç®¡çç³»ç»", |
| | | "VITE_BASE_API": "http://114.132.189.42:9088", |
| | | "VITE_JAVA_API": "http://114.132.189.42:9087" |
| | | }, |
| | | "screen": "screen/DHDCView.png", |
| | | "logo": "logo/CMNYLogo.png", |
| | | "favicon": "favicon/CMNYico.ico" |
| | | }, |
| | | "HCKX": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "æµ·å·å¼å¿é£åä¿¡æ¯ç®¡çç³»ç»", |
| | | "VITE_BASE_API": "http://114.132.189.42:9090", |
| | | "VITE_JAVA_API": "http://114.132.189.42:9089" |
| | | }, |
| | | "screen": "screen/HCKXView.png", |
| | | "logo": "logo/HCKXLogo.png", |
| | | "favicon": "favicon/HCKXico.ico" |
| | | }, |
| | | "JLSN": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "é¦é¾æ°´æ³¥ä¿¡æ¯ç®¡çç³»ç»", |
| | | "VITE_BASE_API": "http://114.132.189.42:9094", |
| | | "VITE_JAVA_API": "http://114.132.189.42:9093" |
| | | }, |
| | | "screen": "screen/JLSNView.png", |
| | | "logo": "logo/JLSNLogo.png", |
| | | "favicon": "favicon/JLSNico.ico" |
| | | }, |
| | | "BDSM": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "åè¾¾å贸信æ¯ç®¡çç³»ç»", |
| | | "VITE_BASE_API": "http://114.132.189.42:9096", |
| | | "VITE_JAVA_API": "http://114.132.189.42:9095" |
| | | }, |
| | | "screen": "screen/BDSMView.png", |
| | | "logo": "logo/BDSMLogo.png", |
| | | "favicon": "favicon/BDSMico.ico" |
| | | }, |
| | | "HXGY": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "æ±æéä¸ä¿¡æ¯ç®¡çç³»ç»", |
| | | "VITE_BASE_API": "http://114.132.189.42:9098", |
| | | "VITE_JAVA_API": "http://114.132.189.42:9097" |
| | | }, |
| | | "screen": "screen/HXGYView.png", |
| | | "logo": "logo/HXGYLogo.png", |
| | | "favicon": "favicon/HXGYico.ico" |
| | | }, |
| | | "ZDXM": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "æå¾·åç
¤ä¿¡æ¯ç®¡çç³»ç»", |
| | | "VITE_BASE_API": "http://114.132.189.42:9100", |
| | | "VITE_JAVA_API": "http://114.132.189.42:9096" |
| | | }, |
| | | "screen": "screen/ZDXMView.png", |
| | | "logo": "logo/ZDXMLogo.png", |
| | | "favicon": "favicon/ZDXMico.ico" |
| | | }, |
| | | "HSX": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "æ¹æ°´å³¡åä¸åå±ä¿¡æ¯ç®¡çç³»ç»", |
| | | "VITE_BASE_API": "http://114.132.189.42:9101", |
| | | "VITE_JAVA_API": "http://114.132.189.42:9098" |
| | | }, |
| | | "screen": "screen/HSXView.png", |
| | | "logo": "logo/HSXLogo.png", |
| | | "favicon": "favicon/HSXico.ico" |
| | | }, |
| | | "NYDL": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "åæ´çµç¼äº§é¾éä¿¡æ¯ç®¡çç³»ç»", |
| | | "VITE_BASE_API": "http://114.132.189.42:9036", |
| | | "VITE_JAVA_API": "http://114.132.189.42:9037" |
| | | }, |
| | | "screen": "screen/NYDLView.png", |
| | | "logo": "logo/NYDLLogo.png", |
| | | "favicon": "favicon/NYDLico.ico" |
| | | }, |
| | | "HCMY": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "浩æç
¤ä¸ä¿¡æ¯ç®¡çç³»ç»", |
| | | "VITE_BASE_API": "http://114.132.189.42:9103", |
| | | "VITE_JAVA_API": "http://114.132.189.42:9094" |
| | | }, |
| | | "screen": "screen/HCMYView.png", |
| | | "logo": "logo/HCMYLogo.png", |
| | | "favicon": "favicon/HCMYico.ico" |
| | | }, |
| | | "HGJJ": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "æ±å½æ´ååç
¤ä¿¡æ¯ç®¡çç³»ç»", |
| | | "VITE_BASE_API": "http://114.132.189.42:9107", |
| | | "VITE_JAVA_API": "http://114.132.189.42:9090" |
| | | }, |
| | | "screen": "screen/HGJJView.png", |
| | | "logo": "logo/HGJJLogo.png", |
| | | "favicon": "favicon/HGJJico.ico" |
| | | }, |
| | | "MKZS": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "模å¯åçä¿¡æ¯ç®¡çç³»ç»", |
| | | "VITE_BASE_API": "http://114.132.189.42:9111", |
| | | "VITE_JAVA_API": "http://114.132.189.42:9086" |
| | | }, |
| | | "screen": "screen/MKZSView.png", |
| | | "logo": "logo/MKZSLogo.png", |
| | | "favicon": "favicon/MKZSico.ico" |
| | | }, |
| | | "HSMY": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "å顺éä¸ä¿¡æ¯ç®¡çç³»ç»", |
| | | "VITE_BASE_API": "http://114.132.189.42:9115", |
| | | "VITE_JAVA_API": "http://114.132.189.42:9082" |
| | | }, |
| | | "screen": "screen/HSMYView.png", |
| | | "logo": "logo/HSMYLogo.png", |
| | | "favicon": "favicon/HSMYico.ico" |
| | | }, |
| | | "DHHB": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "丹海ç¯ä¿ä¿¡æ¯ç®¡çç³»ç»", |
| | | "VITE_BASE_API": "http://114.132.189.42:9117", |
| | | "VITE_JAVA_API": "http://114.132.189.42:9080" |
| | | }, |
| | | "screen": "screen/DHHBView.png", |
| | | "logo": "logo/DHHBLogo.png", |
| | | "favicon": "favicon/DHHBico.ico" |
| | | }, |
| | | "PHMK": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "æ®ç¦¾ç
¤ç¿ä¿¡æ¯ç®¡çç³»ç»", |
| | | "VITE_BASE_API": "http://114.132.189.42:9119", |
| | | "VITE_JAVA_API": "http://114.132.189.42:9078" |
| | | }, |
| | | "screen": "screen/PHMKView.png", |
| | | "logo": "logo/PHMKLogo.png", |
| | | "favicon": "favicon/PHMKico.ico" |
| | | }, |
| | | "TYMK": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "éæºç
¤ç¿ä¿¡æ¯ç®¡çç³»ç»", |
| | | "VITE_BASE_API": "http://114.132.189.42:9121", |
| | | "VITE_JAVA_API": "http://114.132.189.42:9076" |
| | | }, |
| | | "screen": "screen/TYMKView.png", |
| | | "logo": "logo/TYMKLogo.png", |
| | | "favicon": "favicon/TYMKico.ico" |
| | | }, |
| | | "LQM": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "èçªéº¦é£åä¿¡æ¯ç®¡çç³»ç»", |
| | | "VITE_BASE_API": "http://114.132.189.42:9123", |
| | | "VITE_JAVA_API": "http://114.132.189.42:9074" |
| | | }, |
| | | "screen": "screen/LQMView.png", |
| | | "logo": "logo/LQMLogo.png", |
| | | "favicon": "favicon/LQMico.ico" |
| | | }, |
| | | "ZYRQ": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "伿ºçæ°ä¿¡æ¯ç®¡çç³»ç»", |
| | | "VITE_BASE_API": "http://114.132.189.42:9123", |
| | | "VITE_JAVA_API": "http://114.132.189.42:9031" |
| | | }, |
| | | "screen": "screen/ZYRQView.png", |
| | | "logo": "logo/ZYRQLogo.png", |
| | | "favicon": "favicon/ZYRQico.ico" |
| | | }, |
| | | "RTSW": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "润泰çç©ä¿¡æ¯ç®¡çç³»ç»", |
| | | "VITE_BASE_API": "http://114.132.189.42:9066", |
| | | "VITE_JAVA_API": "http://114.132.189.42:9064" |
| | | }, |
| | | "screen": "screen/RTSWView.png", |
| | | "logo": "logo/RTSWLogo.png", |
| | | "favicon": "favicon/RTSWico.ico" |
| | | }, |
| | | "HXSJ": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "åçºç æµä¿¡æ¯ç®¡çç³»ç»", |
| | | "VITE_BASE_API": "http://114.132.189.42:9066", |
| | | "VITE_JAVA_API": "http://114.132.189.42:9062" |
| | | }, |
| | | "screen": "screen/HXSJView.png", |
| | | "logo": "logo/HXSJLogo.png", |
| | | "favicon": "favicon/HXSJico.ico" |
| | | }, |
| | | "QLMC": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "ç¥è¿ç§åºä¿¡æ¯ç®¡çç³»ç»", |
| | | "VITE_BASE_API": "http://114.132.189.42:9066", |
| | | "VITE_JAVA_API": "http://114.132.189.42:9060" |
| | | }, |
| | | "screen": "screen/QLMCView.png", |
| | | "logo": "logo/QLMCLogo.png", |
| | | "favicon": "favicon/QLMCico.ico" |
| | | }, |
| | | "AYNM": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "å®ä½åç§ä¿¡æ¯ç®¡çç³»ç»", |
| | | "VITE_BASE_API": "http://114.132.189.42:9066", |
| | | "VITE_JAVA_API": "http://114.132.189.42:9058" |
| | | }, |
| | | "screen": "screen/AYNMView.png", |
| | | "logo": "logo/AYNMLogo.png", |
| | | "favicon": "favicon/AYNMico.ico" |
| | | }, |
| | | "JMSL": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "éè塿å
è£
ä¿¡æ¯ç®¡çç³»ç»", |
| | | "VITE_BASE_API": "http://114.132.189.42:9066", |
| | | "VITE_JAVA_API": "http://114.132.189.42:9058" |
| | | }, |
| | | "screen": "screen/JMSLView.png", |
| | | "logo": "logo/JMSLLogo.png", |
| | | "favicon": "favicon/JMSLico.ico" |
| | | }, |
| | | "TJKH": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "天津å¯åä¿¡æ¯ç®¡çç³»ç»", |
| | | "VITE_BASE_API": "http://114.132.189.42:9066", |
| | | "VITE_JAVA_API": "http://114.132.189.42:9058" |
| | | }, |
| | | "screen": "screen/TJKHView.png", |
| | | "logo": "logo/TJKHLogo.png", |
| | | "favicon": "favicon/TJKHico.ico" |
| | | }, |
| | | "DZYS": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "䏿³½å°å·ä¿¡æ¯ç®¡çç³»ç»", |
| | | "VITE_BASE_API": "http://114.132.189.42:9066", |
| | | "VITE_JAVA_API": "http://114.132.189.42:9046" |
| | | }, |
| | | "screen": "screen/DZYSView.png", |
| | | "logo": "logo/DZYSLogo.png", |
| | | "favicon": "favicon/DZYSico.ico" |
| | | }, |
| | | "screen": "/src/assets/images/login-background.png", |
| | | "logo": "/src/assets/logo/logo.png", |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import request from "@/utils/request.js"; |
| | | |
| | | export function productModelList(query) { |
| | | return request({ |
| | | url: '/basic/product/pageModel', |
| | | method: 'get', |
| | | params: query |
| | | }) |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import request from '@/utils/request' |
| | | |
| | | // å·¥åºå表å页æ¥è¯¢ |
| | | export function productProcessListPage(query) { |
| | | return request({ |
| | | url: '/productProcess/listPage', |
| | | method: 'get', |
| | | params: query |
| | | }) |
| | | } |
| | |
| | | import request from '@/utils/request' |
| | | import request from "@/utils/request"; |
| | | |
| | | // æ¥è¯¢å
¬åå表 |
| | | export function listNotice(query) { |
| | | return request({ |
| | | url: '/collaborativeApproval/notice/page', |
| | | method: 'get', |
| | | params: query |
| | | }) |
| | | return request({ |
| | | url: "/collaborativeApproval/notice/page", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | |
| | | // æ¥è¯¢å
¬åè¯¦ç» |
| | | export function getNotice(noticeId) { |
| | | return request({ |
| | | url: '/collaborativeApproval/notice/' + noticeId, |
| | | method: 'get' |
| | | }) |
| | | return request({ |
| | | url: "/collaborativeApproval/notice/" + noticeId, |
| | | method: "get", |
| | | }); |
| | | } |
| | | |
| | | // æ°å¢å
Œ |
| | | export function addNotice(data) { |
| | | return request({ |
| | | url: '/collaborativeApproval/notice/add', |
| | | method: 'post', |
| | | data: data |
| | | }) |
| | | return request({ |
| | | url: "/collaborativeApproval/notice/add", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | |
| | | // ä¿®æ¹å
Œ |
| | | export function updateNotice(data) { |
| | | return request({ |
| | | url: '/collaborativeApproval/notice/update', |
| | | method: 'put', |
| | | data: data |
| | | }) |
| | | return request({ |
| | | url: "/collaborativeApproval/notice/update", |
| | | method: "put", |
| | | data: data, |
| | | }); |
| | | } |
| | | |
| | | // å é¤å
Œ |
| | | export function delNotice(ids) { |
| | | return request({ |
| | | url: '/collaborativeApproval/notice/' + ids, |
| | | method: 'delete', |
| | | }) |
| | | return request({ |
| | | url: "/collaborativeApproval/notice/" + ids, |
| | | method: "delete", |
| | | }); |
| | | } |
| | | |
| | | // è·åå
¬åæ°é |
| | | export function getCount() { |
| | | return request({ |
| | | url: '/collaborativeApproval/notice/count', |
| | | method: 'get', |
| | | }) |
| | | return request({ |
| | | url: "/collaborativeApproval/notice/count", |
| | | method: "get", |
| | | }); |
| | | } |
| | | |
| | | // æ¥è¯¢å
¬åç±»åå表 |
| | | export function listNoticeType() { |
| | | return request({ |
| | | url: '/noticeType/list', |
| | | method: 'get' |
| | | }) |
| | | return request({ |
| | | url: "/noticeType/list", |
| | | method: "get", |
| | | }); |
| | | } |
| | | |
| | | // æ°å¢å
¬åç±»å |
| | | export function addNoticeType(data) { |
| | | return request({ |
| | | url: '/noticeType/add', |
| | | method: 'post', |
| | | data: data |
| | | }) |
| | | return request({ |
| | | url: "/noticeType/add", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | |
| | | // å é¤å
¬åç±»å |
| | | export function delNoticeType(id) { |
| | | return request({ |
| | | url: '/noticeType/del', |
| | | method: 'delete', |
| | | data: { id } |
| | | }) |
| | | } |
| | | return request({ |
| | | url: "/noticeType/del", |
| | | method: "delete", |
| | | data: [id], |
| | | }); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // åè´§å®¡æ¹ |
| | | import request from "@/utils/request"; |
| | | |
| | | // è·åå货审æ¹å表 |
| | | export function getShipmentApprovalList(query) { |
| | | return request({ |
| | | url: '/shipmentApproval/listPage', |
| | | method: 'get', |
| | | params: query, |
| | | }) |
| | | } |
| | | |
| | | // åè´§ç³è¯·æ¹å |
| | | // /shipmentApproval/update |
| | | export function approveShipment(query) { |
| | | return request({ |
| | | url: '/shipmentApproval/update', |
| | | method: 'post', |
| | | data: query, |
| | | }) |
| | | } |
| | |
| | | method: "post", |
| | | data: query, |
| | | }); |
| | | } |
| | | |
| | | // 计éå¨å
·å°è´¦-æ°å¢ |
| | | // /measuringInstrumentLedger/add |
| | | export function addMeasuringInstrumentLedger(data){ |
| | | return request({ |
| | | url:"/measuringInstrumentLedger/add", |
| | | method:"post", |
| | | data |
| | | }) |
| | | } |
| | | |
| | | // 计éå¨å
·å°è´¦-ç¼è¾ |
| | | // /measuringInstrumentLedger/update |
| | | export function updateMeasuringInstrumentLedger(data){ |
| | | return request({ |
| | | url:"/measuringInstrumentLedger/update", |
| | | method:"post", |
| | | data |
| | | }) |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import request from "@/utils/request"; |
| | | |
| | | // è·ååºå®èµäº§æ±æ»ä¿¡æ¯ |
| | | export const getAccountingTotal = (params) => { |
| | | return request({ |
| | | url: "/accounting/total", |
| | | method: "get", |
| | | params, |
| | | }); |
| | | }; |
| | | |
| | | // è·å设å¤ç±»åå叿°æ®ï¼é¥¼å¾åæçº¿å¾ï¼ |
| | | export const getDeviceTypeDistribution = (params) => { |
| | | return request({ |
| | | url: "/accounting/deviceTypeDistribution", |
| | | method: "get", |
| | | params, |
| | | }); |
| | | }; |
| | | |
| | | // è·åææ§è®¡ç®æ°æ®ï¼è¡¨æ ¼æ°æ®ï¼ |
| | | export const getCalculateDepreciation = (params) => { |
| | | return request({ |
| | | url: "/accounting/calculateDepreciation", |
| | | method: "get", |
| | | params, |
| | | }); |
| | | }; |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import request from "@/utils/request"; |
| | | |
| | | // æ¥è¯¢å表 |
| | | export const listPage = (params) => { |
| | | return request({ |
| | | url: "/borrowInfo/listPage", |
| | | method: "get", |
| | | params, |
| | | }); |
| | | }; |
| | | |
| | | // æ°å¢ |
| | | export function add(data) { |
| | | return request({ |
| | | url: "/borrowInfo/add", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | |
| | | // ç¼è¾ |
| | | export function update(data) { |
| | | return request({ |
| | | url: "/borrowInfo/update", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | |
| | | // å é¤ |
| | | export const delAccountLoan = (data) => { |
| | | return request({ |
| | | url: "/borrowInfo/delete", |
| | | method: "delete", |
| | | data, |
| | | }); |
| | | }; |
| | |
| | | }); |
| | | }; |
| | | |
| | | // æ¥è¯¢ç产å
¥åºä¿¡æ¯å表 |
| | | export const getStockInPageByProduction = (params) => { |
| | | return request({ |
| | | url: "/stockin/listPageByProduction", |
| | | method: "get", |
| | | params, |
| | | }); |
| | | }; |
| | | |
| | | // æ¥è¯¢ç产å
¥åºä¿¡æ¯å表 |
| | | export const getStockInPageByProductProduction = (params) => { |
| | | return request({ |
| | | url: "/stockin/listPageByProductProduction", |
| | | method: "get", |
| | | params, |
| | | }); |
| | | }; |
| | | |
| | | // åºåºå°è´¦-æ¥è¯¢èªå®ä¹å
¥åºä¿¡æ¯å表 |
| | | export const getStockInPageByCustom = (params) => { |
| | | return request({ |
| | | url: "/stockmanagement/listPageByCustom", |
| | | method: "get", |
| | | params, |
| | | }); |
| | | }; |
| | | // å
¥åºç®¡ç-æ¥è¯¢èªå®ä¹å
¥åºä¿¡æ¯å表 |
| | | export const getInPageByCustom = (params) => { |
| | | return request({ |
| | | url: "/stockin/listPageByCustom", |
| | | method: "get", |
| | | params, |
| | | }); |
| | | }; |
| | | |
| | | // åºåºå°è´¦-æ¥è¯¢ç产åºåºä¿¡æ¯å表 |
| | | export const getStockInPageByProduct = (params) => { |
| | | return request({ |
| | | url: "/stockmanagement/listPageByProduct", |
| | | method: "get", |
| | | params, |
| | | }); |
| | | }; |
| | | |
| | | // ä¿®æ¹å
¥åºåä¿¡æ¯ |
| | | export const updateStockIn = (data) => { |
| | | return request({ |
| | |
| | | data, |
| | | }); |
| | | }; |
| | | // ä¿®æ¹ææåºåä¿¡æ¯ |
| | | export const updateManagementByCustom = (data) => { |
| | | return request({ |
| | | url: "/stockin/updateManagementByCustom ", |
| | | method: "post", |
| | | data, |
| | | }); |
| | | }; |
| | | |
| | | // æ°å¢ååå
¥åºä¿¡æ¯ |
| | | export function addSutockIn(data) { |
| | |
| | | }) |
| | | } |
| | | |
| | | // æ°å¢èªå®ä¹å
¥åºä¿¡æ¯ |
| | | export function addStockInCustom(data) { |
| | | return request({ |
| | | url: '/stockin/addCustom', |
| | | method: 'post', |
| | | data: data |
| | | }) |
| | | } |
| | | |
| | | // ç¼è¾èªå®ä¹å
¥åºä¿¡æ¯ |
| | | export function updateStockInCustom(data) { |
| | | return request({ |
| | | url: '/stockin/updateCustom', |
| | | method: 'post', |
| | | data: data |
| | | }) |
| | | } |
| | | // ç¼è¾æåå
¥åºä¿¡æ¯ |
| | | export function updateProduct(data) { |
| | | return request({ |
| | | url: '/stockin/update', |
| | | method: 'post', |
| | | data: data |
| | | }) |
| | | } |
| | | |
| | | // å é¤å
¥åºä¿¡æ¯ |
| | | export function delStockIn(ids) { |
| | | return request({ |
| | |
| | | }) |
| | | } |
| | | |
| | | // å é¤èªå®ä¹å
¥åºä¿¡æ¯ |
| | | export function delStockInCustom(ids) { |
| | | return request({ |
| | | url: '/stockin/delteCustom', |
| | | method: 'post', |
| | | data: ids |
| | | }) |
| | | } |
| | | |
| | | // 导åºå
¥åºä¿¡æ¯ |
| | | export function exportStockIn(query) { |
| | | return request({ |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import request from "@/utils/request"; |
| | | |
| | | // æ¥è¯¢å
¥åºä¿¡æ¯å表 |
| | | export const getStockInRecordListPage = (params) => { |
| | | return request({ |
| | | url: "/stockInRecord/listPage", |
| | | method: "get", |
| | | params, |
| | | }); |
| | | }; |
| | | |
| | | |
| | | export const updateStockInRecord = (id, data) => { |
| | | return request({ |
| | | url: "/stockInRecord/" + id, |
| | | method: "put", |
| | | data: data, |
| | | }); |
| | | }; |
| | | |
| | | export const batchDeleteStockInRecords = (ids) => { |
| | | return request({ |
| | | url: "/stockInRecord", |
| | | method: "delete", |
| | | data: ids, |
| | | }); |
| | | }; |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import request from "@/utils/request.js"; |
| | | // å页æ¥è¯¢åºåè®°å½å表 |
| | | export const getStockInventoryListPage = (params) => { |
| | | return request({ |
| | | url: "/stockInventory/pagestockInventory", |
| | | method: "get", |
| | | params, |
| | | }); |
| | | }; |
| | | |
| | | // å建åºåè®°å½ |
| | | export const createStockInventory = (params) => { |
| | | return request({ |
| | | url: "/stockInventory/addstockInventory", |
| | | method: "post", |
| | | params, |
| | | }); |
| | | }; |
| | | |
| | | // åå°åºåè®°å½ |
| | | export const subtractStockInventory = (params) => { |
| | | return request({ |
| | | url: "/stockInventory/subtractStockInventory", |
| | | method: "post", |
| | | params, |
| | | }); |
| | | }; |
| | |
| | | }); |
| | | }; |
| | | |
| | | // æ¥è¯¢ç产å
¥åºåºåä¿¡æ¯å表 |
| | | export const getStockManagePageByProduction = (params) => { |
| | | return request({ |
| | | url: "/stockin/listPageCopyByProduction", |
| | | method: "get", |
| | | params, |
| | | }); |
| | | }; |
| | | // æ¥è¯¢æååºåä¿¡æ¯å表 |
| | | export const getStockManageProduction = (params) => { |
| | | return request({ |
| | | url: "/stockin/listPageProductionStock", |
| | | method: "get", |
| | | params, |
| | | }); |
| | | }; |
| | | // æ¥è¯¢èªå®ä¹å
¥åºåºåä¿¡æ¯å表 |
| | | export const getStockManagePageByCustom = (params) => { |
| | | return request({ |
| | | url: "/stockin/listPageCopyByCustom", |
| | | method: "get", |
| | | params, |
| | | }); |
| | | }; |
| | | |
| | | |
| | | // ä¿®æ¹åºåä¿¡æ¯ |
| | | export const updateStockManage = (data) => { |
| | |
| | | }) |
| | | } |
| | | |
| | | //åºåºæ¥å£ |
| | | // åºåºç®¡ç-é¢ç¨æ¥å£ |
| | | export const stockOut = (data) => { |
| | | return request({ |
| | | url: '/stockmanagement/stockout', |
| | |
| | | import request from "@/utils/request"; |
| | | |
| | | //æ¥è¯¢åºåºå表 |
| | | // åºåºå°è´¦-éè´åºåºæ¥è¯¢åºåºå表 |
| | | export const getStockOutPage = (params) => { |
| | | return request({ |
| | | url: "/stockmanagement/listPage", |
| | | url: "/stockOutRecord/listPage", |
| | | method: "get", |
| | | params, |
| | | }); |
| | | }; |
| | | |
| | | //æ°å¢åºåºä¿¡æ¯ |
| | | export const addStockOut = (data) => { |
| | | return request({ |
| | | url: '/stockout/add', |
| | | method: 'post', |
| | | data: data |
| | | }) |
| | | } |
| | | |
| | | //ä¿®æ¹åºåºä¿¡æ¯ |
| | | export const updateStockOut = (data) => { |
| | | return request({ |
| | | url: "/stockout/update", |
| | | method: "put", |
| | | data, |
| | | }); |
| | | } |
| | | |
| | | //å é¤åºåºä¿¡æ¯ |
| | | export const delStockOut = (ids) => { |
| | | return request({ |
| | | url: '/stockmanagement/del', |
| | | method: 'post', |
| | | data: ids |
| | | }) |
| | | url: "/stockOutRecord", |
| | | method: "delete", |
| | | data: ids, |
| | | }); |
| | | } |
| | | |
| | | //导åºåºåºä¿¡æ¯ |
| | | export const exportStockOut = (query) => { |
| | | return request({ |
| | | url: '/stockmanagement/export', |
| | | method: 'get', |
| | | params: query, |
| | | responseType: 'blob' |
| | | }) |
| | | } |
| | |
| | | method: 'get', |
| | | params: query, |
| | | }) |
| | | } |
| | | |
| | | // 导åºåå坿¬ |
| | | export function staffOnJobExportCopy(data) { |
| | | return request({ |
| | | url: '/staff/staffOnJob/exportCopy', |
| | | method: 'post', |
| | | data: data, |
| | | }) |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import request from "@/utils/request.js"; |
| | | |
| | | // 离èåå åæ |
| | | export function findStaffLeaveReasonAnalysis() { |
| | | return request({ |
| | | url: "/staff/analytics/reason", |
| | | method: "get" |
| | | }); |
| | | } |
| | | |
| | | // 12个æåå·¥æµå¨æµå¤±çåæ |
| | | export function findStaffAnalysisMonthlyTurnoverRateFor12Months() { |
| | | return request({ |
| | | url: "/staff/analytics/monthly_turnover_rate", |
| | | method: "get" |
| | | }); |
| | | } |
| | | |
| | | export function findStaffAnalysisTotalStatistic() { |
| | | return request({ |
| | | url: "/staff/analytics/total_statistic", |
| | | method: "get" |
| | | }); |
| | | } |
| | | |
| | | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import request from "@/utils/request.js"; |
| | | |
| | | |
| | | export function findStaffContractListPage(query) { |
| | | return request({ |
| | | url: "/staff/staffContract/listPage", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import request from "@/utils/request.js"; |
| | | |
| | | export function findStaffLeaveListPage(query) { |
| | | return request({ |
| | | url: "/staff/staffLeave/listPage", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | |
| | | export function createStaffLeave(data) { |
| | | return request({ |
| | | url: "/staff/staffLeave", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | |
| | | export function updateStaffLeave(id, data) { |
| | | return request({ |
| | | url: "/staff/staffLeave/" + id, |
| | | method: "put", |
| | | data: data, |
| | | }); |
| | | } |
| | | |
| | | export function batchDeleteStaffLeaves(data) { |
| | | return request({ |
| | | url: "/staff/staffLeave/del", |
| | | method: "delete", |
| | | data: data, |
| | | }); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import request from '@/utils/request' |
| | | |
| | | // æ¥è¯¢å¨èåå·¥å°è´¦ |
| | | export function staffOnJobListPage(query) { |
| | | return request({ |
| | | url: '/staff/staffOnJob/listPage', |
| | | method: 'get', |
| | | params: query, |
| | | }) |
| | | } |
| | | // æ¥è¯¢åå·¥å
¥èä¿¡æ¯ |
| | | export function staffOnJobInfo(id, query) { |
| | | return request({ |
| | | url: '/staff/staffOnJob/' + id, |
| | | method: 'get', |
| | | params: query, |
| | | }) |
| | | } |
| | | |
| | | // æ°å¢åå·¥ |
| | | export function createStaffOnJob(params) { |
| | | return request({ |
| | | url: "/staff/staffOnJob", |
| | | method: "post", |
| | | data: params, |
| | | }); |
| | | } |
| | | |
| | | // ä¿®æ¹åå·¥ |
| | | export function updateStaffOnJob(id, params) { |
| | | return request({ |
| | | url: "/staff/staffOnJob/" + id, |
| | | method: "put", |
| | | data: params, |
| | | }); |
| | | } |
| | | |
| | | // å é¤åå·¥ |
| | | export function batchDeleteStaffOnJobs(query) { |
| | | return request({ |
| | | url: "/staff/staffOnJob/del", |
| | | method: "delete", |
| | | data: query, |
| | | }); |
| | | } |
| | | |
| | | // ç»ç¾åå |
| | | export function renewContract(id, params) { |
| | | return request({ |
| | | url: "/staff/staffOnJob/renewContract/" + id, |
| | | method: "post", |
| | | data: params, |
| | | }); |
| | | } |
| | |
| | | // æ¥è¯¢å表 |
| | | export function invoiceListPage(query) { |
| | | return request({ |
| | | url: "/purchase/registration/listPage", |
| | | url: "/sales/product/listPagePurchaseLedger", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // éè´æ¥è¡¨é¡µé¢æ¥å£ |
| | | import request from "@/utils/request"; |
| | | |
| | | // éè´ä¸å¡æ±æ»è¡¨å页æ¥è¯¢ |
| | | export function procurementBusinessSummaryListPage(query) { |
| | | return request({ |
| | | url: "/procurementBusinessSummary/listPage", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // å·¥èºè·¯çº¿é¡µé¢æ¥å£ |
| | | import request from "@/utils/request"; |
| | | |
| | | // å页æ¥è¯¢ |
| | | export function listPage(query) { |
| | | return request({ |
| | | url: "/processRoute/page", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | |
| | | export function add(data) { |
| | | return request({ |
| | | url: "/processRoute", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | |
| | | export function del(ids) { |
| | | return request({ |
| | | url: '/processRoute/' + ids, |
| | | method: 'delete', |
| | | }) |
| | | } |
| | | |
| | | export function update(data) { |
| | | return request({ |
| | | url: '/processRoute', |
| | | method: 'put', |
| | | data: data, |
| | | }) |
| | | } |
| | | |
| | | // è·å详æ
|
| | | export function getById(id) { |
| | | return request({ |
| | | url: `/processRoute/${id}`, |
| | | method: 'get', |
| | | }) |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // å·¥èºè·¯çº¿é¡¹ç®é¡µé¢æ¥å£ |
| | | import request from "@/utils/request"; |
| | | |
| | | // å表æ¥è¯¢ |
| | | export function findProcessRouteItemList(query) { |
| | | return request({ |
| | | url: "/processRouteItem/list", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | |
| | | export function addOrUpdateProcessRouteItem(data) { |
| | | return request({ |
| | | url: "/processRouteItem", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | |
| | | // æåºæ¥å£ |
| | | export function sortProcessRouteItem(data) { |
| | | return request({ |
| | | url: "/processRouteItem/sort", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | |
| | | // æ¹éå 餿¥å£ |
| | | export function batchDeleteProcessRouteItem(ids) { |
| | | // å°idæ°ç»è½¬æ¢ä¸ºéå·åéçåç¬¦ä¸²ï¼æ¼æ¥å°URLåé¢ |
| | | const idsStr = Array.isArray(ids) ? ids.join(",") : ids; |
| | | return request({ |
| | | url: `/processRouteItem/batchDelete/${idsStr}`, |
| | | method: "delete", |
| | | }); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // 产åBOM页颿¥å£ |
| | | import request from "@/utils/request"; |
| | | |
| | | // å页æ¥è¯¢ |
| | | export function listPage(query) { |
| | | return request({ |
| | | url: "/productBom/listPage", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | |
| | | // æ°å¢ |
| | | export function add(data) { |
| | | return request({ |
| | | url: "/productBom/add", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | |
| | | // ä¿®æ¹ |
| | | export function update(data) { |
| | | return request({ |
| | | url: "/productBom/update", |
| | | method: "put", |
| | | data: data, |
| | | }); |
| | | } |
| | | |
| | | // æ¹éå é¤ |
| | | export function batchDelete(ids) { |
| | | return request({ |
| | | url: "/productBom/batchDelete", |
| | | method: "delete", |
| | | data: ids, |
| | | }); |
| | | } |
| | | |
| | | // æ ¹æ®äº§ååå·IDæ¥è¯¢BOM |
| | | export function getByModel(productModelId) { |
| | | return request({ |
| | | url: "/productBom/getByModel", |
| | | method: "get", |
| | | params: { productModelId }, |
| | | }); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // å·¥èºè·¯çº¿é¡¹ç®é¡µé¢æ¥å£ |
| | | import request from "@/utils/request"; |
| | | |
| | | // å表æ¥è¯¢ |
| | | export function findProductProcessRouteItemList(query) { |
| | | return request({ |
| | | url: "/productProcessRoute/list", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | |
| | | export function addOrUpdateProductProcessRouteItem(data) { |
| | | return request({ |
| | | url: "/productProcessRoute/updateRouteItem", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | |
| | | // ç产订åä¸ï¼æ°å¢å·¥èºè·¯çº¿é¡¹ç® |
| | | export function addRouteItem(data) { |
| | | return request({ |
| | | url: "/productProcessRoute/addRouteItem", |
| | | method: "post", |
| | | data, |
| | | }); |
| | | } |
| | | |
| | | // è·åç产订åå
³èçå·¥èºè·¯çº¿ä¸»ä¿¡æ¯ |
| | | export function listMain(orderId) { |
| | | return request({ |
| | | url: "/productProcessRoute/listMain", |
| | | method: "get", |
| | | params: { orderId }, |
| | | }); |
| | | } |
| | | |
| | | // å é¤å·¥èºè·¯çº¿é¡¹ç®ï¼è·¯ç±åæ¼æ¥ idï¼ |
| | | export function deleteRouteItem(id) { |
| | | return request({ |
| | | url: `/productProcessRoute/deleteRouteItem/${id}`, |
| | | method: "delete", |
| | | }); |
| | | } |
| | | |
| | | // ç产订åä¸ï¼æåºå·¥èºè·¯çº¿é¡¹ç® |
| | | export function sortRouteItem(data) { |
| | | return request({ |
| | | url: "/productProcessRoute/sortRouteItem", |
| | | method: "post", |
| | | data, |
| | | }); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // 产åç»æé¡µé¢æ¥å£ |
| | | import request from "@/utils/request"; |
| | | |
| | | // å页æ¥è¯¢ |
| | | export function queryList(id) { |
| | | return request({ |
| | | url: "/productStructure/listBybomId/" + id, |
| | | method: "get", |
| | | }); |
| | | } |
| | | |
| | | export function add(data) { |
| | | return request({ |
| | | url: "/productStructure", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | |
| | | params: query, |
| | | }); |
| | | } |
| | | |
| | | export function productOrderListPage(query) { |
| | | return request({ |
| | | url: "/productOrder/page", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | |
| | | // ç产订å-æäº§ååå·æ¥è¯¢å¯ç¨å·¥èºè·¯çº¿å表 |
| | | export function listProcessRoute(query) { |
| | | return request({ |
| | | url: "/productOrder/listProcessRoute", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | |
| | | // ç产订å-ç»å®å·¥èºè·¯çº¿ |
| | | export function bindingRoute(data) { |
| | | return request({ |
| | | url: "/productOrder/bindingRoute", |
| | | method: "post", |
| | | data, |
| | | }); |
| | | } |
| | | |
| | | // ç产订å-æ¥è¯¢äº§åç»æå表 |
| | | export function listProcessBom(query) { |
| | | return request({ |
| | | url: "/productOrder/listProcessBom", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | |
| | | // è·åçæºæ£å¨å·¥ä½éæ°æ® |
| | | export function schedulingList(query) { |
| | | return request({ |
| | | url: "/salesLedger/scheduling/list", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | |
| | | // ä¿åçæºè®¾ç½® |
| | | export function addSpeculatTrading(data) { |
| | | return request({ |
| | | url: "/salesLedger/scheduling/addSpeculatTrading", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | |
| | | // ä¿®æ¹çæºè®¾ç½® |
| | | export function updateSpeculatTrading(data) { |
| | | return request({ |
| | | url: "/salesLedger/scheduling/updateSpeculatTrading", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | |
| | | // ç产派工 |
| | | export function productionDispatch(query) { |
| | | return request({ |
| | |
| | | method: "post", |
| | | data: query, |
| | | }); |
| | | } |
| | | // èªå¨æ´¾å·¥ |
| | | export function productionDispatchList(query) { |
| | | return request({ |
| | | url: "/salesLedger/scheduling/productionDispatchList", |
| | | method: "post", |
| | | data: query, |
| | | }); |
| | | } |
| | | |
| | | // æ¥è¯¢æèç |
| | | export function getLossRate() { |
| | | return request({ |
| | | url: "/salesLedger/scheduling/loss", |
| | | method: "get", |
| | | }); |
| | | } |
| | | |
| | | // æ°å¢æèç |
| | | export function addLossRate(data) { |
| | | return request({ |
| | | url: "/salesLedger/scheduling/addLoss", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | |
| | | // ä¿®æ¹æèç |
| | | export function updateLossRate(data) { |
| | | return request({ |
| | | url: "/salesLedger/scheduling/updateLoss", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // å·¥åºé¡µé¢æ¥å£ |
| | | import request from "@/utils/request"; |
| | | |
| | | // å页æ¥è¯¢ |
| | | export function listPage(query) { |
| | | return request({ |
| | | url: "/productProcess/listPage", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | |
| | | export function processList(query) { |
| | | return request({ |
| | | url: "/productProcess/list", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | |
| | | export function add(data) { |
| | | return request({ |
| | | url: "/productProcess", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | |
| | | export function del(data) { |
| | | return request({ |
| | | url: '/productProcess/batchDelete', |
| | | method: 'delete', |
| | | data: data, |
| | | }) |
| | | } |
| | | |
| | | export function update(data) { |
| | | return request({ |
| | | url: '/productProcess/update', |
| | | method: 'put', |
| | | data: data, |
| | | }) |
| | | } |
| | | |
| | | // å·¥åºæ¥è¯¢ |
| | | export function list() { |
| | | return request({ |
| | | url: "/productProcess/list", |
| | | method: "get", |
| | | }); |
| | | } |
| | | |
| | | // 导å
¥æ°æ® |
| | | export function importData(data) { |
| | | return request({ |
| | | url: "/productProcess/importData", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | |
| | | // ä¸è½½æ¨¡æ¿ |
| | | export function downloadTemplate() { |
| | | return request({ |
| | | url: "/productProcess/downloadTemplate", |
| | | method: "post", |
| | | responseType: "blob", |
| | | }); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // ç产æå
¥é¡µé¢æ¥å£ |
| | | import request from "@/utils/request"; |
| | | |
| | | // å页æ¥è¯¢ |
| | | export function productionProductInputListPage(query) { |
| | | return request({ |
| | | url: "/productionProductInput/listPage", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // ç产æ¥å·¥é¡µé¢æ¥å£ |
| | | import request from "@/utils/request"; |
| | | |
| | | // å页æ¥è¯¢ |
| | | export function productionProductMainListPage(query) { |
| | | return request({ |
| | | url: "/productionProductMain/listPage", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // ç产产åºé¡µé¢æ¥å£ |
| | | import request from "@/utils/request"; |
| | | |
| | | // å页æ¥è¯¢ |
| | | export function productionProductOutputListPage(query) { |
| | | return request({ |
| | | url: "/productionProductOutput/listPage", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | |
| | | method: "post", |
| | | data: query, |
| | | }); |
| | | } |
| | | } |
| | | // ç产æ¥å·¥-å é¤ |
| | | export function productionReportDelete(query) { |
| | | return request({ |
| | | url: "/productionProductMain/delete", |
| | | method: "delete", |
| | | data: query, |
| | | }); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import request from "@/utils/request"; |
| | | |
| | | export function productWorkOrderPage(query) { |
| | | return request({ |
| | | url: "/productWorkOrder/page", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | |
| | | export function updateProductWorkOrder(data) { |
| | | return request({ |
| | | url: "/productWorkOrder/updateProductWorkOrder", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | |
| | | export function addProductMain(data) { |
| | | return request({ |
| | | url: "/productionProductMain/addProductMain", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | |
| | | import request from '@/utils/request' |
| | | import request from "@/utils/request"; |
| | | |
| | | // æ¥è¯¢ææ å表 |
| | | export function qualityTestStandardListPage(query) { |
| | | return request({ |
| | | url: '/quality/qualityTestStandard/listPage', |
| | | method: 'get', |
| | | params: query, |
| | | }) |
| | | return request({ |
| | | url: "/qualityTestStandard/listPage", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | |
| | | // æ°å¢ææ å表 |
| | | export function qualityTestStandardAdd(query) { |
| | | return request({ |
| | | url: '/quality/qualityTestStandard/add', |
| | | method: 'post', |
| | | data: query, |
| | | }) |
| | | return request({ |
| | | url: "/qualityTestStandard/add", |
| | | method: "post", |
| | | data: query, |
| | | }); |
| | | } |
| | | |
| | | // ä¿®æ¹ææ å表 |
| | | export function qualityTestStandardUpdate(query) { |
| | | return request({ |
| | | url: '/quality/qualityTestStandard/update', |
| | | method: 'post', |
| | | data: query, |
| | | }) |
| | | return request({ |
| | | url: "/qualityTestStandard/update", |
| | | method: "post", |
| | | data: query, |
| | | }); |
| | | } |
| | | |
| | | // å 餿æ å表 |
| | | export function qualityTestStandardDel(query) { |
| | | return request({ |
| | | url: '/quality/qualityTestStandard/del', |
| | | method: 'delete', |
| | | data: query, |
| | | }) |
| | | return request({ |
| | | url: "/qualityTestStandard/del", |
| | | method: "delete", |
| | | data: query, |
| | | }); |
| | | } |
| | | |
| | | // å 餿æ å表 |
| | | export function qualityInspectDetailByProductId(productId) { |
| | | return request({ |
| | | url: '/quality/qualityTestStandard/product/' + productId, |
| | | method: 'get', |
| | | }) |
| | | } |
| | | export function qualityInspectDetailByProductId(params) { |
| | | return request({ |
| | | url: "/qualityTestStandard/getQualityTestStandardByProductId", |
| | | method: "get", |
| | | params: params, |
| | | }); |
| | | } |
| | | |
| | | // å¤å¶æ ååæ° |
| | | export function qualityTestStandardCopyParam(id) { |
| | | return request({ |
| | | url: "/qualityTestStandard/copyParam", |
| | | method: "post", |
| | | data: { id }, |
| | | }); |
| | | } |
| | | |
| | | // æ¹éå®¡æ ¸ï¼ç¶æï¼1=éè¿/æ¹åï¼2=æ¤éï¼ |
| | | // ä¼ åï¼[{ id, state }] |
| | | export function qualityTestStandardAudit(data) { |
| | | return request({ |
| | | url: "/qualityTestStandard/qualityTestStandardAudit", |
| | | method: "post", |
| | | data, |
| | | }); |
| | | } |
| | | |
| | | // æ ååæ°ï¼å表ï¼ä¸åé¡µï¼ |
| | | export function qualityTestStandardParamList(query) { |
| | | return request({ |
| | | url: "/qualityTestStandardParam/list", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | |
| | | // æ ååæ°ï¼æ°å¢ |
| | | export function qualityTestStandardParamAdd(data) { |
| | | return request({ |
| | | url: "/qualityTestStandardParam/add", |
| | | method: "post", |
| | | data, |
| | | }); |
| | | } |
| | | |
| | | // æ ååæ°ï¼ä¿®æ¹ |
| | | export function qualityTestStandardParamUpdate(data) { |
| | | return request({ |
| | | url: "/qualityTestStandardParam/update", |
| | | method: "post", |
| | | data, |
| | | }); |
| | | } |
| | | |
| | | // æ ååæ°ï¼å é¤ï¼ä¼ id æ°ç»ï¼ |
| | | export function qualityTestStandardParamDel(ids) { |
| | | return request({ |
| | | url: "/qualityTestStandardParam/del", |
| | | method: "delete", |
| | | data: ids, |
| | | }); |
| | | } |
| | | |
| | | // æ ¹æ®æ åIDè·åæ ååæ° |
| | | export function getQualityTestStandardParamByTestStandardId(testStandardId) { |
| | | return request({ |
| | | url: "/qualityTestStandard/getQualityTestStandardParamByTestStandardId", |
| | | method: "get", |
| | | params: { testStandardId }, |
| | | }); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import request from "@/utils/request"; |
| | | |
| | | // ç»å®å表ï¼ä¸åé¡µï¼ |
| | | export function qualityTestStandardBindingList(query) { |
| | | return request({ |
| | | url: "/qualityTestStandardBinding/list", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | |
| | | // æ°å¢ç»å®ï¼æ¯ææ¹éï¼ |
| | | export function qualityTestStandardBindingAdd(data) { |
| | | return request({ |
| | | url: "/qualityTestStandardBinding/add", |
| | | method: "post", |
| | | data, |
| | | }); |
| | | } |
| | | |
| | | // å é¤ç»å®ï¼ä¼ id æ°ç»ï¼ |
| | | export function qualityTestStandardBindingDel(ids) { |
| | | return request({ |
| | | url: "/qualityTestStandardBinding/del", |
| | | method: "delete", |
| | | data: ids, |
| | | }); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import request from '@/utils/request' |
| | | |
| | | // è·ååç±»å宿æ°é |
| | | export function getInspectStatistics() { |
| | | return request({ |
| | | url: '/qualityReport/getInspectStatistics', |
| | | method: 'get' |
| | | }) |
| | | } |
| | | |
| | | // è·åè´¨æ£åæ ¼çç»è®¡ |
| | | export function getPassRateStatistics() { |
| | | return request({ |
| | | url: '/qualityReport/getPassRateStatistics', |
| | | method: 'get' |
| | | }) |
| | | } |
| | | |
| | | // è·åæåº¦åæ ¼çç»è®¡æ°æ® |
| | | export function getMonthlyPassRateStatistics(year) { |
| | | return request({ |
| | | url: '/qualityReport/getMonthlyPassRateStatistics', |
| | | method: 'get', |
| | | params: { year } |
| | | }) |
| | | } |
| | | |
| | | // è·å年度æ»åæ ¼çç»è®¡æ°æ® |
| | | export function getYearlyPassRateStatistics(year) { |
| | | return request({ |
| | | url: '/qualityReport/getYearlyPassRateStatistics', |
| | | method: 'get', |
| | | params: { year } |
| | | }) |
| | | } |
| | | // è·åæåº¦å®ææç»æ°æ® |
| | | export function getMonthlyCompletionDetails(year) { |
| | | return request({ |
| | | url: '/qualityReport/getMonthlyCompletionDetails', |
| | | method: 'get', |
| | | params: { year } |
| | | }) |
| | | } |
| | | |
| | | // è·åçç¹æ£æµææ ç»è®¡ |
| | | export function getTopParameters(inspectType) { |
| | | return request({ |
| | | url: '/qualityReport/getTopParameters', |
| | | method: 'get', |
| | | params: { inspectType } |
| | | }) |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // ææ ç»è®¡é¡µé¢æ¥å£ |
| | | import request from "@/utils/request"; |
| | | |
| | | // 头é¨ç»è®¡æ¥å£ |
| | | export function getTotalStatistics(query) { |
| | | return request({ |
| | | url: "/metricStatistics/total", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | |
| | | // æ±ç¶å¾æ°æ®æ¥å£ |
| | | export function getStatisticsTable(query) { |
| | | return request({ |
| | | url: "/metricStatistics/statisticsTable", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | |
| | | // æ¥è¯¢å·²ç»ç»å®å票çå¼ç¥¨å°è´¦ |
| | | export function bindInvoiceNoRegPage(query) { |
| | | return request({ |
| | | url: '/receiptPayment/bindInvoiceNoRegPage', |
| | | url: '/sales/product/listPageSalesLedger', |
| | | method: 'get', |
| | | params: query |
| | | }) |
| | |
| | | // ä¸é®æ è®°æææ¶æ¯ä¸ºå·²è¯» |
| | | export function markAllAsRead() { |
| | | return request({ |
| | | url: "/system/notice/markAllAsRead", |
| | | url: "/system/notice/readAll", |
| | | method: "post", |
| | | }); |
| | | } |
| | |
| | | })
|
| | | }
|
| | |
|
| | | export function findPostOptions(query) {
|
| | | return request({
|
| | | url: '/system/post/optionselect',
|
| | | method: 'get',
|
| | | params: query
|
| | | })
|
| | | }
|
| | |
|
| | |
|
| | | // æ¥è¯¢å²ä½è¯¦ç»
|
| | | export function getPost(postId) {
|
| | | return request({
|
| | |
| | | url: '/sales/ledger/getAmountHalfYear', |
| | | method: 'get' |
| | | }) |
| | | } |
| | | |
| | | // åç产订åç宿è¿åº¦ç»è®¡ |
| | | // /home/progressStatistics |
| | | export const getProgressStatistics = ()=>{ |
| | | return request({ |
| | | url: '/home/progressStatistics', |
| | | method: 'get' |
| | | }) |
| | | } |
| | | |
| | | //å¨å¶åå¨è½¬æ
åµ |
| | | //home/workInProcessTurnover |
| | | export const getWorkInProcessTurnover= ()=>{ |
| | | return request({ |
| | | url: '/home/workInProcessTurnover', |
| | | method: 'get' |
| | | }) |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="40" height="40" viewBox="0 0 40 40"><defs><mask id="master_svg0_88_35670" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="40" height="40"><ellipse cx="20" cy="20" rx="20" ry="20" fill="#FFFFFF" fill-opacity="1"/></mask><clipPath id="master_svg1_88_35666"><rect x="7" y="7" width="27" height="27" rx="0"/></clipPath><linearGradient x1="0.5" y1="0" x2="0.5" y2="1" id="master_svg2_88_26531"><stop offset="0%" stop-color="#FFFFFF" stop-opacity="1"/><stop offset="98.57142567634583%" stop-color="#F0FBFF" stop-opacity="1"/></linearGradient><linearGradient x1="0.5" y1="0" x2="0.5" y2="1" id="master_svg3_88_26531"><stop offset="0%" stop-color="#FFFFFF" stop-opacity="1"/><stop offset="98.57142567634583%" stop-color="#F0FBFF" stop-opacity="1"/></linearGradient></defs><g mask="url(#master_svg0_88_35670)"><ellipse cx="20" cy="20" rx="20" ry="20" fill="#0092FF" fill-opacity="1"/><g clip-path="url(#master_svg1_88_35666)"><path d="M21.175671875,27.58515925L14.263672875000001,27.58515925C13.750673275,27.58515925,13.426672974999999,27.24765625,13.426672974999999,26.74815725C13.426672974999999,26.23515525,13.764173075,25.911160250000002,14.263672875000001,25.911160250000002L21.351173875,25.911160250000002C21.688676875,24.89865825,22.188173875,23.88615425,22.863174875,23.211156250000002L14.263672875000001,23.211156250000002C13.750673275,23.211156250000002,13.426672974999999,22.87365525,13.426672974999999,22.37415225C13.426672974999999,21.87465325,13.764173075,21.537155249999998,14.263672875000001,21.537155249999998L25.738675875,21.537155249999998C26.251674875,21.37515325,26.751174875,21.37515325,27.088676875,21.37515325C28.438678875,21.37515325,29.626676875,21.88815525,30.625678875,22.549656249999998L30.625678875,13.072656349999999C30.625678875,11.38515625,29.275674875,10.03515625,27.588174875,10.03515625L27.075177875,10.03515625L27.075177875,13.24815675C27.075177875,14.935656550000001,25.725173875,16.285657450000002,24.037676875000002,16.285657450000002L16.113174475,16.285657450000002C14.425674475000001,16.272157149999998,13.075673375000001,14.922158249999999,13.075673375000001,13.23465635L13.075673375000001,10.03515625L12.238672475,10.03515625C10.551171974999999,10.03515625,9.201171875,11.38515625,9.201171875,13.072656349999999L9.201171875,29.94765825C9.201171875,31.63515625,10.551171974999999,32.985161250000004,12.238672475,32.985161250000004L25.576673875,32.985161250000004C23.200674875,32.485662250000004,21.337675875000002,30.28515825,21.175671875,27.58515925Z" fill="url(#master_svg2_88_26531)" fill-opacity="1" style="mix-blend-mode:passthrough"/><path d="M16.1124145625,14.764538762499999L24.0504169625,14.764538762499999C24.8874170625,14.764538762499999,25.5624140625,14.0895385625,25.5624140625,13.252537762500001L25.5624140625,10.0395388625L22.5249171625,10.0395388625C22.3629159625,8.8650390625,21.3369150625,7.8525390625,19.986915562500002,7.8525390625C18.7989153625,7.8525390625,17.7864150625,8.8650390625,17.6244149625,10.0395388625L14.5869140625,10.0395388625L14.5869140625,13.252537762500001C14.5869140625,14.0895385625,15.2619143725,14.764538762499999,16.1124145625,14.764538762499999ZM30.7869150625,24.3900370625C29.9499160625,23.3775360625,28.5999220625,22.7025380625,27.2499170625,22.7025380625L26.412916062500003,22.7025380625C25.8999180625,22.7025380625,25.5759160625,22.8780390625,25.0629190625,23.2155400625C24.0504169625,23.7285370625,23.1999158625,24.7275330625,22.700415562499998,25.9155390625C22.5384173625,26.4285390625,22.5384173625,26.9280380625,22.5384173625,27.4275380625L22.5384173625,27.5895390625C22.700415562499998,30.1275410625,24.7254170625,31.9770390625,27.1014200625,31.9770390625C28.4514180625,31.9770390625,29.8014230625,31.3020400625,30.6384180625,30.2895320625C31.3134210625,29.4525340625,31.6509170625,28.4265380625,31.6509170625,27.2520330625C31.8129160625,26.2395310625,31.2999250625,25.2270370625,30.7869150625,24.3900370625ZM29.7879200625,26.5770380625L27.0879160625,29.2770390625C26.7504160625,29.6145400625,26.412916062500003,29.6145400625,26.0754160625,29.2770390625L24.387915562499998,27.5895390625C24.0504169625,27.2520370625,24.0504169625,26.9145390625,24.387915562499998,26.5770380625C24.725415062499998,26.2395380625,25.0629150625,26.2395400625,25.4004160625,26.5770380625L26.2374170625,27.4140400625L26.5749150625,27.7515370625L28.7619150625,25.5645350625C29.0994140625,25.2270370625,29.4369190625,25.2270370625,29.774416062500002,25.5645350625C30.1119160625,25.9020370625,30.1119160625,26.2395380625,29.7879200625,26.5770380625Z" fill="url(#master_svg3_88_26531)" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></g></svg> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="40" height="40" viewBox="0 0 40 40"><defs><mask id="master_svg0_88_35670" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="40" height="40"><ellipse cx="20" cy="20" rx="20" ry="20" fill="#FFFFFF" fill-opacity="1"/></mask><clipPath id="master_svg1_88_35666"><rect x="7" y="7" width="27" height="27" rx="0"/></clipPath><linearGradient x1="0.5" y1="0" x2="0.5" y2="1" id="master_svg2_88_26531"><stop offset="0%" stop-color="#FFFFFF" stop-opacity="1"/><stop offset="98.57142567634583%" stop-color="#F0FBFF" stop-opacity="1"/></linearGradient><linearGradient x1="0.5" y1="0" x2="0.5" y2="1" id="master_svg3_88_26531"><stop offset="0%" stop-color="#FFFFFF" stop-opacity="1"/><stop offset="98.57142567634583%" stop-color="#F0FBFF" stop-opacity="1"/></linearGradient></defs><g mask="url(#master_svg0_88_35670)"><ellipse cx="20" cy="20" rx="20" ry="20" fill="#5EB334" fill-opacity="1"/><g clip-path="url(#master_svg1_88_35666)"><path d="M21.175671875,27.58515925L14.263672875000001,27.58515925C13.750673275,27.58515925,13.426672974999999,27.24765625,13.426672974999999,26.74815725C13.426672974999999,26.23515525,13.764173075,25.911160250000002,14.263672875000001,25.911160250000002L21.351173875,25.911160250000002C21.688676875,24.89865825,22.188173875,23.88615425,22.863174875,23.211156250000002L14.263672875000001,23.211156250000002C13.750673275,23.211156250000002,13.426672974999999,22.87365525,13.426672974999999,22.37415225C13.426672974999999,21.87465325,13.764173075,21.537155249999998,14.263672875000001,21.537155249999998L25.738675875,21.537155249999998C26.251674875,21.37515325,26.751174875,21.37515325,27.088676875,21.37515325C28.438678875,21.37515325,29.626676875,21.88815525,30.625678875,22.549656249999998L30.625678875,13.072656349999999C30.625678875,11.38515625,29.275674875,10.03515625,27.588174875,10.03515625L27.075177875,10.03515625L27.075177875,13.24815675C27.075177875,14.935656550000001,25.725173875,16.285657450000002,24.037676875000002,16.285657450000002L16.113174475,16.285657450000002C14.425674475000001,16.272157149999998,13.075673375000001,14.922158249999999,13.075673375000001,13.23465635L13.075673375000001,10.03515625L12.238672475,10.03515625C10.551171974999999,10.03515625,9.201171875,11.38515625,9.201171875,13.072656349999999L9.201171875,29.94765825C9.201171875,31.63515625,10.551171974999999,32.985161250000004,12.238672475,32.985161250000004L25.576673875,32.985161250000004C23.200674875,32.485662250000004,21.337675875000002,30.28515825,21.175671875,27.58515925Z" fill="url(#master_svg2_88_26531)" fill-opacity="1" style="mix-blend-mode:passthrough"/><path d="M16.1124145625,14.764538762499999L24.0504169625,14.764538762499999C24.8874170625,14.764538762499999,25.5624140625,14.0895385625,25.5624140625,13.252537762500001L25.5624140625,10.0395388625L22.5249171625,10.0395388625C22.3629159625,8.8650390625,21.3369150625,7.8525390625,19.986915562500002,7.8525390625C18.7989153625,7.8525390625,17.7864150625,8.8650390625,17.6244149625,10.0395388625L14.5869140625,10.0395388625L14.5869140625,13.252537762500001C14.5869140625,14.0895385625,15.2619143725,14.764538762499999,16.1124145625,14.764538762499999ZM30.7869150625,24.3900370625C29.9499160625,23.3775360625,28.5999220625,22.7025380625,27.2499170625,22.7025380625L26.412916062500003,22.7025380625C25.8999180625,22.7025380625,25.5759160625,22.8780390625,25.0629190625,23.2155400625C24.0504169625,23.7285370625,23.1999158625,24.7275330625,22.700415562499998,25.9155390625C22.5384173625,26.4285390625,22.5384173625,26.9280380625,22.5384173625,27.4275380625L22.5384173625,27.5895390625C22.700415562499998,30.1275410625,24.7254170625,31.9770390625,27.1014200625,31.9770390625C28.4514180625,31.9770390625,29.8014230625,31.3020400625,30.6384180625,30.2895320625C31.3134210625,29.4525340625,31.6509170625,28.4265380625,31.6509170625,27.2520330625C31.8129160625,26.2395310625,31.2999250625,25.2270370625,30.7869150625,24.3900370625ZM29.7879200625,26.5770380625L27.0879160625,29.2770390625C26.7504160625,29.6145400625,26.412916062500003,29.6145400625,26.0754160625,29.2770390625L24.387915562499998,27.5895390625C24.0504169625,27.2520370625,24.0504169625,26.9145390625,24.387915562499998,26.5770380625C24.725415062499998,26.2395380625,25.0629150625,26.2395400625,25.4004160625,26.5770380625L26.2374170625,27.4140400625L26.5749150625,27.7515370625L28.7619150625,25.5645350625C29.0994140625,25.2270370625,29.4369190625,25.2270370625,29.774416062500002,25.5645350625C30.1119160625,25.9020370625,30.1119160625,26.2395380625,29.7879200625,26.5770380625Z" fill="url(#master_svg3_88_26531)" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></g></svg> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="40" height="40" viewBox="0 0 40 40"><defs><mask id="master_svg0_88_35670" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="40" height="40"><ellipse cx="20" cy="20" rx="20" ry="20" fill="#FFFFFF" fill-opacity="1"/></mask><clipPath id="master_svg1_88_35666"><rect x="7" y="7" width="27" height="27" rx="0"/></clipPath><linearGradient x1="0.5" y1="0" x2="0.5" y2="1" id="master_svg2_88_26531"><stop offset="0%" stop-color="#FFFFFF" stop-opacity="1"/><stop offset="98.57142567634583%" stop-color="#F0FBFF" stop-opacity="1"/></linearGradient><linearGradient x1="0.5" y1="0" x2="0.5" y2="1" id="master_svg3_88_26531"><stop offset="0%" stop-color="#FFFFFF" stop-opacity="1"/><stop offset="98.57142567634583%" stop-color="#F0FBFF" stop-opacity="1"/></linearGradient></defs><g mask="url(#master_svg0_88_35670)"><ellipse cx="20" cy="20" rx="20" ry="20" fill="#8000FF" fill-opacity="1"/><g clip-path="url(#master_svg1_88_35666)"><path d="M21.175671875,27.58515925L14.263672875000001,27.58515925C13.750673275,27.58515925,13.426672974999999,27.24765625,13.426672974999999,26.74815725C13.426672974999999,26.23515525,13.764173075,25.911160250000002,14.263672875000001,25.911160250000002L21.351173875,25.911160250000002C21.688676875,24.89865825,22.188173875,23.88615425,22.863174875,23.211156250000002L14.263672875000001,23.211156250000002C13.750673275,23.211156250000002,13.426672974999999,22.87365525,13.426672974999999,22.37415225C13.426672974999999,21.87465325,13.764173075,21.537155249999998,14.263672875000001,21.537155249999998L25.738675875,21.537155249999998C26.251674875,21.37515325,26.751174875,21.37515325,27.088676875,21.37515325C28.438678875,21.37515325,29.626676875,21.88815525,30.625678875,22.549656249999998L30.625678875,13.072656349999999C30.625678875,11.38515625,29.275674875,10.03515625,27.588174875,10.03515625L27.075177875,10.03515625L27.075177875,13.24815675C27.075177875,14.935656550000001,25.725173875,16.285657450000002,24.037676875000002,16.285657450000002L16.113174475,16.285657450000002C14.425674475000001,16.272157149999998,13.075673375000001,14.922158249999999,13.075673375000001,13.23465635L13.075673375000001,10.03515625L12.238672475,10.03515625C10.551171974999999,10.03515625,9.201171875,11.38515625,9.201171875,13.072656349999999L9.201171875,29.94765825C9.201171875,31.63515625,10.551171974999999,32.985161250000004,12.238672475,32.985161250000004L25.576673875,32.985161250000004C23.200674875,32.485662250000004,21.337675875000002,30.28515825,21.175671875,27.58515925Z" fill="url(#master_svg2_88_26531)" fill-opacity="1" style="mix-blend-mode:passthrough"/><path d="M16.1124145625,14.764538762499999L24.0504169625,14.764538762499999C24.8874170625,14.764538762499999,25.5624140625,14.0895385625,25.5624140625,13.252537762500001L25.5624140625,10.0395388625L22.5249171625,10.0395388625C22.3629159625,8.8650390625,21.3369150625,7.8525390625,19.986915562500002,7.8525390625C18.7989153625,7.8525390625,17.7864150625,8.8650390625,17.6244149625,10.0395388625L14.5869140625,10.0395388625L14.5869140625,13.252537762500001C14.5869140625,14.0895385625,15.2619143725,14.764538762499999,16.1124145625,14.764538762499999ZM30.7869150625,24.3900370625C29.9499160625,23.3775360625,28.5999220625,22.7025380625,27.2499170625,22.7025380625L26.412916062500003,22.7025380625C25.8999180625,22.7025380625,25.5759160625,22.8780390625,25.0629190625,23.2155400625C24.0504169625,23.7285370625,23.1999158625,24.7275330625,22.700415562499998,25.9155390625C22.5384173625,26.4285390625,22.5384173625,26.9280380625,22.5384173625,27.4275380625L22.5384173625,27.5895390625C22.700415562499998,30.1275410625,24.7254170625,31.9770390625,27.1014200625,31.9770390625C28.4514180625,31.9770390625,29.8014230625,31.3020400625,30.6384180625,30.2895320625C31.3134210625,29.4525340625,31.6509170625,28.4265380625,31.6509170625,27.2520330625C31.8129160625,26.2395310625,31.2999250625,25.2270370625,30.7869150625,24.3900370625ZM29.7879200625,26.5770380625L27.0879160625,29.2770390625C26.7504160625,29.6145400625,26.412916062500003,29.6145400625,26.0754160625,29.2770390625L24.387915562499998,27.5895390625C24.0504169625,27.2520370625,24.0504169625,26.9145390625,24.387915562499998,26.5770380625C24.725415062499998,26.2395380625,25.0629150625,26.2395400625,25.4004160625,26.5770380625L26.2374170625,27.4140400625L26.5749150625,27.7515370625L28.7619150625,25.5645350625C29.0994140625,25.2270370625,29.4369190625,25.2270370625,29.774416062500002,25.5645350625C30.1119160625,25.9020370625,30.1119160625,26.2395380625,29.7879200625,26.5770380625Z" fill="url(#master_svg3_88_26531)" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></g></svg> |
| | |
| | | |
| | | const handleUpload = async () => { |
| | | if (props.uploadMethod) { |
| | | const newItem = await props.uploadMethod() |
| | | if (newItem) { |
| | | addAttachment(newItem) |
| | | } |
| | | // 妿æä¾äºèªå®ä¹ä¸ä¼ æ¹æ³ï¼ç±ç¶ç»ä»¶è´è´£æ´æ°å表ï¼éè¿ setListï¼ |
| | | // è¿éä¸åèªå¨æ·»å ï¼é¿å
ä¸ç¶ç»ä»¶ç setList éå¤ |
| | | await props.uploadMethod() |
| | | } |
| | | emit('upload') |
| | | } |
| | |
| | | :fixed="item.fixed" |
| | | :label="item.label" |
| | | :prop="item.prop" |
| | | show-overflow-tooltip |
| | | :show-overflow-tooltip="item.dataType !== 'action' && item.dataType !== 'slot'" |
| | | :align="item.align" |
| | | :sortable="!!item.sortable" |
| | | :type="item.type" |
| | | :width="item.width" |
| | | > |
| | | <template #header="scope"> |
| | | <div class="pim-table-header-cell"> |
| | | <div class="pim-table-header-title"> |
| | | {{ item.label }} |
| | | </div> |
| | | <div v-if="item.headerSlot" class="pim-table-header-extra"> |
| | | <slot :name="item.headerSlot" :column="scope.column" /> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | <template |
| | | v-if="item.hasOwnProperty('colunmTemplate')" |
| | | #[item.colunmTemplate]="scope" |
| | |
| | | </div> |
| | | |
| | | <!-- æé® --> |
| | | <div v-else-if="item.dataType == 'action'"> |
| | | <div v-else-if="item.dataType == 'action'" @click.stop> |
| | | <template v-for="(o, key) in item.operation" :key="key"> |
| | | <el-button |
| | | v-show="o.type != 'upload'" |
| | |
| | | : o.color, |
| | | }" |
| | | link |
| | | @click="o.clickFun(scope.row)" |
| | | @click.stop="o.clickFun(scope.row)" |
| | | :key="key" |
| | | > |
| | | {{ o.name }} |
| | |
| | | </el-table-column> |
| | | </el-table> |
| | | <pagination |
| | | v-if="isShowPagination" |
| | | :total="page.total" |
| | | :layout="page.layout" |
| | | :page="page.current" |
| | |
| | | isSelection: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | isShowPagination: { |
| | | type: Boolean, |
| | | default: true, |
| | | }, |
| | | isShowSummary: { |
| | | type: Boolean, |
| | |
| | | padding-right: 0 !important; |
| | | padding-left: 0 !important; |
| | | } |
| | | |
| | | .pim-table-header-extra :deep(.el-input), |
| | | .pim-table-header-extra :deep(.el-select) { |
| | | width: 100%; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="page-header-wrapper"> |
| | | <el-page-header @back="handleBack" :content="content"> |
| | | <template #icon v-if="$slots.icon"> |
| | | <slot name="icon"></slot> |
| | | </template> |
| | | <template #title v-if="$slots.title"> |
| | | <slot name="title"></slot> |
| | | </template> |
| | | <template #content v-if="$slots.content"> |
| | | <slot name="content"></slot> |
| | | </template> |
| | | <template #extra> |
| | | <slot name="extra"> |
| | | <slot name="right-button"></slot> |
| | | </slot> |
| | | </template> |
| | | </el-page-header> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { useRouter } from 'vue-router' |
| | | |
| | | const props = defineProps({ |
| | | content: { |
| | | type: String, |
| | | default: '' |
| | | } |
| | | }) |
| | | |
| | | const emit = defineEmits(['back']) |
| | | |
| | | const router = useRouter() |
| | | |
| | | const handleBack = () => { |
| | | emit('back') |
| | | // é»è®¤è¿åå°ä¸ä¸çº§ |
| | | router.back() |
| | | } |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .page-header-wrapper { |
| | | margin-bottom: 16px; |
| | | } |
| | | |
| | | .page-header-wrapper :deep(.el-page-header__extra) { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 8px; |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <div class="qr-code-generator"> |
| | | <!-- äºç»´ç çæè¡¨å --> |
| | | <el-form :model="form" :rules="rules" ref="formRef" label-width="120px" class="qr-form"> |
| | | <el-form :model="form" |
| | | :rules="rules" |
| | | ref="formRef" |
| | | label-width="120px" |
| | | class="qr-form"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ è¯ç±»å" prop="type"> |
| | | <el-select v-model="form.type" placeholder="è¯·éæ©æ è¯ç±»å" style="width: 100%"> |
| | | <el-option label="äºç»´ç " value="qrcode"></el-option> |
| | | <el-option label="é²ä¼ªç " value="security"></el-option> |
| | | <el-form-item label="æ è¯ç±»å" |
| | | prop="type"> |
| | | <el-select v-model="form.type" |
| | | placeholder="è¯·éæ©æ è¯ç±»å" |
| | | style="width: 100%"> |
| | | <el-option label="äºç»´ç " |
| | | value="qrcode"></el-option> |
| | | <el-option label="é²ä¼ªç " |
| | | value="security"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å
容" prop="content"> |
| | | <el-input |
| | | v-model="form.content" |
| | | placeholder="请è¾å
¥è¦ç¼ç çå
容" |
| | | :type="form.type === 'security' ? 'textarea' : 'text'" |
| | | :rows="form.type === 'security' ? 3 : 1" |
| | | ></el-input> |
| | | <el-form-item label="å
容" |
| | | prop="content"> |
| | | <el-input v-model="form.content" |
| | | placeholder="请è¾å
¥è¦ç¼ç çå
容" |
| | | :type="form.type === 'security' ? 'textarea' : 'text'" |
| | | :rows="form.type === 'security' ? 3 : 1"></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="尺寸" prop="size"> |
| | | <el-input-number |
| | | v-model="form.size" |
| | | :min="100" |
| | | :max="500" |
| | | :step="50" |
| | | style="width: 100%" |
| | | ></el-input-number> |
| | | <el-form-item label="尺寸" |
| | | prop="size"> |
| | | <el-input-number v-model="form.size" |
| | | :min="100" |
| | | :max="500" |
| | | :step="50" |
| | | style="width: 100%"></el-input-number> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="è¾¹è·" prop="margin"> |
| | | <el-input-number |
| | | v-model="form.margin" |
| | | :min="0" |
| | | :max="10" |
| | | :step="1" |
| | | style="width: 100%" |
| | | ></el-input-number> |
| | | <el-form-item label="è¾¹è·" |
| | | prop="margin"> |
| | | <el-input-number v-model="form.margin" |
| | | :min="0" |
| | | :max="10" |
| | | :step="1" |
| | | style="width: 100%"></el-input-number> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="忝è²" prop="foregroundColor"> |
| | | <el-color-picker v-model="form.foregroundColor" style="width: 100%"></el-color-picker> |
| | | <el-form-item label="忝è²" |
| | | prop="foregroundColor"> |
| | | <el-color-picker v-model="form.foregroundColor" |
| | | style="width: 100%"></el-color-picker> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="èæ¯è²" prop="backgroundColor"> |
| | | <el-color-picker v-model="form.backgroundColor" style="width: 100%"></el-color-picker> |
| | | <el-form-item label="èæ¯è²" |
| | | prop="backgroundColor"> |
| | | <el-color-picker v-model="form.backgroundColor" |
| | | style="width: 100%"></el-color-picker> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="24"> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="generateCode" :loading="generating"> |
| | | <el-button type="primary" |
| | | @click="generateCode" |
| | | :loading="generating"> |
| | | çæ{{ form.type === 'qrcode' ? 'äºç»´ç ' : 'é²ä¼ªç ' }} |
| | | </el-button> |
| | | <el-button @click="resetForm">éç½®</el-button> |
| | |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | |
| | | <!-- çæçç æ¾ç¤ºåºå --> |
| | | <div v-if="generatedCodeUrl" class="code-display"> |
| | | <div v-if="generatedCodeUrl" |
| | | class="code-display"> |
| | | <el-divider content-position="center"> |
| | | {{ form.type === 'qrcode' ? 'çæçäºç»´ç ' : 'çæçé²ä¼ªç ' }} |
| | | </el-divider> |
| | | |
| | | <div class="code-container"> |
| | | <div class="code-image"> |
| | | <img :src="generatedCodeUrl" :alt="form.type === 'qrcode' ? 'äºç»´ç ' : 'é²ä¼ªç '" /> |
| | | <img :src="generatedCodeUrl" |
| | | :alt="form.type === 'qrcode' ? 'äºç»´ç ' : 'é²ä¼ªç '" /> |
| | | </div> |
| | | |
| | | <div class="code-info"> |
| | | <p><strong>å
容ï¼</strong>{{ form.content }}</p> |
| | | <p><strong>ç±»åï¼</strong>{{ form.type === 'qrcode' ? 'äºç»´ç ' : 'é²ä¼ªç ' }}</p> |
| | |
| | | <p><strong>çææ¶é´ï¼</strong>{{ generateTime }}</p> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="code-actions"> |
| | | <el-button type="success" @click="downloadCode" icon="Download"> |
| | | <el-button type="success" |
| | | @click="downloadCode" |
| | | icon="Download"> |
| | | ä¸è½½å¾ç |
| | | </el-button> |
| | | <el-button type="primary" @click="copyToClipboard" icon="CopyDocument"> |
| | | <el-button type="primary" |
| | | @click="copyToClipboard" |
| | | icon="CopyDocument"> |
| | | å¤å¶å
容 |
| | | </el-button> |
| | | <el-button @click="printCode" icon="Printer"> |
| | | <el-button @click="printCode" |
| | | icon="Printer"> |
| | | æå° |
| | | </el-button> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- æ¹éçæå¯¹è¯æ¡ --> |
| | | <el-dialog v-model="batchDialogVisible" title="æ¹éçæ" width="600px"> |
| | | <el-form :model="batchForm" label-width="120px"> |
| | | <el-dialog v-model="batchDialogVisible" |
| | | title="æ¹éçæ" |
| | | width="600px"> |
| | | <el-form :model="batchForm" |
| | | label-width="120px"> |
| | | <el-form-item label="çææ°é"> |
| | | <el-input-number v-model="batchForm.quantity" :min="1" :max="100" style="width: 100%"></el-input-number> |
| | | <el-input-number v-model="batchForm.quantity" |
| | | :min="1" |
| | | :max="100" |
| | | style="width: 100%"></el-input-number> |
| | | </el-form-item> |
| | | <el-form-item label="åç¼"> |
| | | <el-input v-model="batchForm.prefix" placeholder="请è¾å
¥åç¼ï¼å¦ï¼PROD_"></el-input> |
| | | <el-input v-model="batchForm.prefix" |
| | | placeholder="请è¾å
¥åç¼ï¼å¦ï¼PROD_"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="èµ·å§ç¼å·"> |
| | | <el-input-number v-model="batchForm.startNumber" :min="1" style="width: 100%"></el-input-number> |
| | | <el-input-number v-model="batchForm.startNumber" |
| | | :min="1" |
| | | style="width: 100%"></el-input-number> |
| | | </el-form-item> |
| | | </el-form> |
| | | |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="generateBatchCodes">å¼å§çæ</el-button> |
| | | <el-button @click="batchDialogVisible = false">åæ¶</el-button> |
| | | <el-button type="primary" @click="generateBatchCodes">å¼å§çæ</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- æ¹éçæç»æ --> |
| | | <div v-if="batchCodes.length > 0" class="batch-results"> |
| | | <div v-if="batchCodes.length > 0" |
| | | class="batch-results"> |
| | | <el-divider content-position="center">æ¹éçæç»æ</el-divider> |
| | | |
| | | <div class="batch-grid"> |
| | | <div |
| | | v-for="(code, index) in batchCodes" |
| | | :key="index" |
| | | class="batch-item" |
| | | > |
| | | <img :src="code.url" :alt="code.content" /> |
| | | <div v-for="(code, index) in batchCodes" |
| | | :key="index" |
| | | class="batch-item"> |
| | | <img :src="code.url" |
| | | :alt="code.content" /> |
| | | <p class="batch-content">{{ code.content }}</p> |
| | | <el-button size="small" @click="downloadSingleCode(code)">ä¸è½½</el-button> |
| | | <el-button size="small" |
| | | @click="downloadSingleCode(code)">ä¸è½½</el-button> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="batch-actions"> |
| | | <el-button type="success" @click="downloadAllCodes">ä¸è½½å
¨é¨</el-button> |
| | | <el-button type="success" |
| | | @click="downloadAllCodes">ä¸è½½å
¨é¨</el-button> |
| | | <el-button @click="clearBatchCodes">æ¸
ç©ºç»æ</el-button> |
| | | </div> |
| | | </div> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, computed, onMounted } from 'vue' |
| | | import QRCode from 'qrcode' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | import { Download, CopyDocument, Printer } from '@element-plus/icons-vue' |
| | | import { ref, reactive, computed, onMounted } from "vue"; |
| | | import QRCode from "qrcode"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import { Download, CopyDocument, Printer } from "@element-plus/icons-vue"; |
| | | |
| | | // å®ä¹ç»ä»¶åç§° |
| | | defineOptions({ |
| | | name: 'QRCodeGenerator' |
| | | }) |
| | | // å®ä¹ç»ä»¶åç§° |
| | | defineOptions({ |
| | | name: "QRCodeGenerator", |
| | | }); |
| | | |
| | | // è¡¨åæ°æ® |
| | | const form = reactive({ |
| | | type: 'qrcode', |
| | | content: '', |
| | | size: 200, |
| | | margin: 2, |
| | | foregroundColor: '#000000', |
| | | backgroundColor: '#FFFFFF' |
| | | }) |
| | | // è¡¨åæ°æ® |
| | | const form = reactive({ |
| | | type: "qrcode", |
| | | content: "", |
| | | size: 200, |
| | | margin: 2, |
| | | foregroundColor: "#000000", |
| | | backgroundColor: "#FFFFFF", |
| | | }); |
| | | |
| | | // 表åéªè¯è§å |
| | | const rules = { |
| | | type: [{ required: true, message: 'è¯·éæ©æ è¯ç±»å', trigger: 'change' }], |
| | | content: [{ required: true, message: '请è¾å
¥å
容', trigger: 'blur' }] |
| | | } |
| | | // 表åéªè¯è§å |
| | | const rules = { |
| | | type: [{ required: true, message: "è¯·éæ©æ è¯ç±»å", trigger: "change" }], |
| | | content: [{ required: true, message: "请è¾å
¥å
容", trigger: "blur" }], |
| | | }; |
| | | |
| | | // ååºå¼æ°æ® |
| | | const formRef = ref() |
| | | const generating = ref(false) |
| | | const generatedCodeUrl = ref('') |
| | | const generateTime = ref('') |
| | | const batchDialogVisible = ref(false) |
| | | const batchForm = reactive({ |
| | | quantity: 10, |
| | | prefix: '', |
| | | startNumber: 1 |
| | | }) |
| | | const batchCodes = ref([]) |
| | | // ååºå¼æ°æ® |
| | | const formRef = ref(); |
| | | const generating = ref(false); |
| | | const generatedCodeUrl = ref(""); |
| | | const generateTime = ref(""); |
| | | const batchDialogVisible = ref(false); |
| | | const batchForm = reactive({ |
| | | quantity: 10, |
| | | prefix: "", |
| | | startNumber: 1, |
| | | }); |
| | | const batchCodes = ref([]); |
| | | |
| | | // çæäºç»´ç æé²ä¼ªç |
| | | const generateCode = async () => { |
| | | try { |
| | | await formRef.value.validate() |
| | | |
| | | if (!form.content.trim()) { |
| | | ElMessage.warning('请è¾å
¥è¦ç¼ç çå
容') |
| | | return |
| | | } |
| | | |
| | | generating.value = true |
| | | |
| | | if (form.type === 'qrcode') { |
| | | // çæäºç»´ç |
| | | generatedCodeUrl.value = await QRCode.toDataURL(form.content, { |
| | | width: form.size, |
| | | margin: form.margin, |
| | | color: { |
| | | dark: form.foregroundColor, |
| | | light: form.backgroundColor |
| | | }, |
| | | errorCorrectionLevel: 'M' |
| | | }) |
| | | } else { |
| | | // çæé²ä¼ªç ï¼ä½¿ç¨äºç»´ç ææ¯ï¼ä½å
å®¹æ ¼å¼ä¸åï¼ |
| | | const securityContent = generateSecurityCode(form.content) |
| | | generatedCodeUrl.value = await QRCode.toDataURL(securityContent, { |
| | | width: form.size, |
| | | margin: form.margin, |
| | | color: { |
| | | dark: form.foregroundColor, |
| | | light: form.backgroundColor |
| | | }, |
| | | errorCorrectionLevel: 'H' // é²ä¼ªç ä½¿ç¨æé«çº éçº§å« |
| | | }) |
| | | } |
| | | |
| | | generateTime.value = new Date().toLocaleString() |
| | | ElMessage.success('çææåï¼') |
| | | |
| | | } catch (error) { |
| | | console.error('çæå¤±è´¥:', error) |
| | | ElMessage.error('çæå¤±è´¥ï¼' + error.message) |
| | | } finally { |
| | | generating.value = false |
| | | } |
| | | } |
| | | // çæäºç»´ç æé²ä¼ªç |
| | | const generateCode = async () => { |
| | | try { |
| | | await formRef.value.validate(); |
| | | |
| | | // çæé²ä¼ªç å
容 |
| | | const generateSecurityCode = (content) => { |
| | | const timestamp = Date.now() |
| | | const random = Math.random().toString(36).substr(2, 8) |
| | | return `SEC_${content}_${timestamp}_${random}` |
| | | } |
| | | if (!form.content.trim()) { |
| | | ElMessage.warning("请è¾å
¥è¦ç¼ç çå
容"); |
| | | return; |
| | | } |
| | | |
| | | // ä¸è½½çæçç |
| | | const downloadCode = () => { |
| | | if (!generatedCodeUrl.value) { |
| | | ElMessage.warning('请å
çæç ') |
| | | return |
| | | } |
| | | |
| | | const a = document.createElement('a') |
| | | a.href = generatedCodeUrl.value |
| | | a.download = `${form.type === 'qrcode' ? 'äºç»´ç ' : 'é²ä¼ªç '}_${new Date().getTime()}.png` |
| | | document.body.appendChild(a) |
| | | a.click() |
| | | document.body.removeChild(a) |
| | | ElMessage.success('ä¸è½½æåï¼') |
| | | } |
| | | generating.value = true; |
| | | |
| | | // å¤å¶å
容å°åªè´´æ¿ |
| | | const copyToClipboard = async () => { |
| | | try { |
| | | await navigator.clipboard.writeText(form.content) |
| | | ElMessage.success('å
容已å¤å¶å°åªè´´æ¿') |
| | | } catch (error) { |
| | | // éçº§æ¹æ¡ |
| | | const textArea = document.createElement('textarea') |
| | | textArea.value = form.content |
| | | document.body.appendChild(textArea) |
| | | textArea.select() |
| | | document.execCommand('copy') |
| | | document.body.removeChild(textArea) |
| | | ElMessage.success('å
容已å¤å¶å°åªè´´æ¿') |
| | | } |
| | | } |
| | | |
| | | // æå°ç |
| | | const printCode = () => { |
| | | if (!generatedCodeUrl.value) { |
| | | ElMessage.warning('请å
çæç ') |
| | | return |
| | | } |
| | | |
| | | const printWindow = window.open('', '_blank') |
| | | printWindow.document.write(` |
| | | <html> |
| | | <head> |
| | | <title>æå°${form.type === 'qrcode' ? 'äºç»´ç ' : 'é²ä¼ªç '}</title> |
| | | <style> |
| | | body { text-align: center; padding: 20px; } |
| | | img { max-width: 100%; height: auto; } |
| | | .info { margin: 20px 0; } |
| | | </style> |
| | | </head> |
| | | <body> |
| | | <h2>${form.type === 'qrcode' ? 'äºç»´ç ' : 'é²ä¼ªç '}</h2> |
| | | <img src="${generatedCodeUrl.value}" alt="${form.type === 'qrcode' ? 'äºç»´ç ' : 'é²ä¼ªç '}" /> |
| | | <div class="info"> |
| | | <p><strong>å
容ï¼</strong>${form.content}</p> |
| | | <p><strong>çææ¶é´ï¼</strong>${generateTime.value}</p> |
| | | </div> |
| | | </body> |
| | | </html> |
| | | `) |
| | | printWindow.document.close() |
| | | printWindow.print() |
| | | } |
| | | |
| | | // é置表å |
| | | const resetForm = () => { |
| | | formRef.value.resetFields() |
| | | generatedCodeUrl.value = '' |
| | | generateTime.value = '' |
| | | batchCodes.value = [] |
| | | } |
| | | |
| | | // æ¹éçæ |
| | | const generateBatchCodes = async () => { |
| | | if (!batchForm.prefix.trim()) { |
| | | ElMessage.warning('请è¾å
¥åç¼') |
| | | return |
| | | } |
| | | |
| | | batchCodes.value = [] |
| | | generating.value = true |
| | | |
| | | try { |
| | | for (let i = 0; i < batchForm.quantity; i++) { |
| | | const number = batchForm.startNumber + i |
| | | const content = `${batchForm.prefix}${number.toString().padStart(6, '0')}` |
| | | |
| | | let codeUrl |
| | | if (form.type === 'qrcode') { |
| | | codeUrl = await QRCode.toDataURL(content, { |
| | | if (form.type === "qrcode") { |
| | | // çæäºç»´ç |
| | | generatedCodeUrl.value = await QRCode.toDataURL(form.content, { |
| | | width: form.size, |
| | | margin: form.margin, |
| | | color: { |
| | | dark: form.foregroundColor, |
| | | light: form.backgroundColor |
| | | } |
| | | }) |
| | | light: form.backgroundColor, |
| | | }, |
| | | errorCorrectionLevel: "M", |
| | | }); |
| | | } else { |
| | | const securityContent = generateSecurityCode(content) |
| | | codeUrl = await QRCode.toDataURL(securityContent, { |
| | | // çæé²ä¼ªç ï¼ä½¿ç¨äºç»´ç ææ¯ï¼ä½å
å®¹æ ¼å¼ä¸åï¼ |
| | | const securityContent = generateSecurityCode(form.content); |
| | | generatedCodeUrl.value = await QRCode.toDataURL(securityContent, { |
| | | width: form.size, |
| | | margin: form.margin, |
| | | color: { |
| | | dark: form.foregroundColor, |
| | | light: form.backgroundColor |
| | | } |
| | | }) |
| | | light: form.backgroundColor, |
| | | }, |
| | | errorCorrectionLevel: "H", // é²ä¼ªç ä½¿ç¨æé«çº éçº§å« |
| | | }); |
| | | } |
| | | |
| | | batchCodes.value.push({ |
| | | content, |
| | | url: codeUrl |
| | | }) |
| | | |
| | | generateTime.value = new Date().toLocaleString(); |
| | | ElMessage.success("çææåï¼"); |
| | | } catch (error) { |
| | | console.error("çæå¤±è´¥:", error); |
| | | ElMessage.error("çæå¤±è´¥ï¼" + error.message); |
| | | } finally { |
| | | generating.value = false; |
| | | } |
| | | |
| | | ElMessage.success(`æ¹éçæå®æï¼å
±çæ ${batchForm.quantity} 个ç `) |
| | | batchDialogVisible.value = false |
| | | |
| | | } catch (error) { |
| | | console.error('æ¹éçæå¤±è´¥:', error) |
| | | ElMessage.error('æ¹éçæå¤±è´¥ï¼' + error.message) |
| | | } finally { |
| | | generating.value = false |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // ä¸è½½å个æ¹éçæçç |
| | | const downloadSingleCode = (code) => { |
| | | const a = document.createElement('a') |
| | | a.href = code.url |
| | | a.download = `${code.content}.png` |
| | | document.body.appendChild(a) |
| | | a.click() |
| | | document.body.removeChild(a) |
| | | } |
| | | // çæé²ä¼ªç å
容 |
| | | const generateSecurityCode = content => { |
| | | const timestamp = Date.now(); |
| | | const random = Math.random().toString(36).substr(2, 8); |
| | | return `SEC_${content}_${timestamp}_${random}`; |
| | | }; |
| | | |
| | | // ä¸è½½æææ¹éçæçç |
| | | const downloadAllCodes = async () => { |
| | | if (batchCodes.value.length === 0) { |
| | | ElMessage.warning('没æå¯ä¸è½½çç ') |
| | | return |
| | | } |
| | | |
| | | try { |
| | | // 使ç¨JSZipæå
ä¸è½½ |
| | | const JSZip = await import('jszip') |
| | | const zip = new JSZip.default() |
| | | |
| | | batchCodes.value.forEach((code, index) => { |
| | | // å°base64转æ¢ä¸ºblob |
| | | const base64Data = code.url.split(',')[1] |
| | | const byteCharacters = atob(base64Data) |
| | | const byteNumbers = new Array(byteCharacters.length) |
| | | for (let i = 0; i < byteCharacters.length; i++) { |
| | | byteNumbers[i] = byteCharacters.charCodeAt(i) |
| | | // ä¸è½½çæçç |
| | | const downloadCode = () => { |
| | | if (!generatedCodeUrl.value) { |
| | | ElMessage.warning("请å
çæç "); |
| | | return; |
| | | } |
| | | |
| | | const a = document.createElement("a"); |
| | | a.href = generatedCodeUrl.value; |
| | | a.download = `${ |
| | | form.type === "qrcode" ? "äºç»´ç " : "é²ä¼ªç " |
| | | }_${new Date().getTime()}.png`; |
| | | document.body.appendChild(a); |
| | | a.click(); |
| | | document.body.removeChild(a); |
| | | ElMessage.success("ä¸è½½æåï¼"); |
| | | }; |
| | | |
| | | // å¤å¶å
容å°åªè´´æ¿ |
| | | const copyToClipboard = async () => { |
| | | try { |
| | | await navigator.clipboard.writeText(form.content); |
| | | ElMessage.success("å
容已å¤å¶å°åªè´´æ¿"); |
| | | } catch (error) { |
| | | // éçº§æ¹æ¡ |
| | | const textArea = document.createElement("textarea"); |
| | | textArea.value = form.content; |
| | | document.body.appendChild(textArea); |
| | | textArea.select(); |
| | | document.execCommand("copy"); |
| | | document.body.removeChild(textArea); |
| | | ElMessage.success("å
容已å¤å¶å°åªè´´æ¿"); |
| | | } |
| | | }; |
| | | |
| | | // æå°ç |
| | | const printCode = () => { |
| | | if (!generatedCodeUrl.value) { |
| | | ElMessage.warning("请å
çæç "); |
| | | return; |
| | | } |
| | | |
| | | const printWindow = window.open("", "_blank"); |
| | | printWindow.document.write(` |
| | | <html> |
| | | <head> |
| | | <title>æå°${form.type === "qrcode" ? "äºç»´ç " : "é²ä¼ªç "}</title> |
| | | <style> |
| | | body { text-align: center; padding: 20px; } |
| | | img { max-width: 100%; height: auto; } |
| | | .info { margin: 20px 0; } |
| | | </style> |
| | | </head> |
| | | <body> |
| | | <h2>${form.type === "qrcode" ? "äºç»´ç " : "é²ä¼ªç "}</h2> |
| | | <img src="${generatedCodeUrl.value}" alt="${ |
| | | form.type === "qrcode" ? "äºç»´ç " : "é²ä¼ªç " |
| | | }" /> |
| | | <div class="info"> |
| | | <p><strong>å
容ï¼</strong>${form.content}</p> |
| | | <p><strong>çææ¶é´ï¼</strong>${generateTime.value}</p> |
| | | </div> |
| | | </body> |
| | | </html> |
| | | `); |
| | | printWindow.document.close(); |
| | | printWindow.print(); |
| | | }; |
| | | |
| | | // é置表å |
| | | const resetForm = () => { |
| | | formRef.value.resetFields(); |
| | | generatedCodeUrl.value = ""; |
| | | generateTime.value = ""; |
| | | batchCodes.value = []; |
| | | }; |
| | | |
| | | // æ¹éçæ |
| | | const generateBatchCodes = async () => { |
| | | if (!batchForm.prefix.trim()) { |
| | | ElMessage.warning("请è¾å
¥åç¼"); |
| | | return; |
| | | } |
| | | |
| | | batchCodes.value = []; |
| | | generating.value = true; |
| | | |
| | | try { |
| | | for (let i = 0; i < batchForm.quantity; i++) { |
| | | const number = batchForm.startNumber + i; |
| | | const content = `${batchForm.prefix}${number |
| | | .toString() |
| | | .padStart(6, "0")}`; |
| | | |
| | | let codeUrl; |
| | | if (form.type === "qrcode") { |
| | | codeUrl = await QRCode.toDataURL(content, { |
| | | width: form.size, |
| | | margin: form.margin, |
| | | color: { |
| | | dark: form.foregroundColor, |
| | | light: form.backgroundColor, |
| | | }, |
| | | }); |
| | | } else { |
| | | const securityContent = generateSecurityCode(content); |
| | | codeUrl = await QRCode.toDataURL(securityContent, { |
| | | width: form.size, |
| | | margin: form.margin, |
| | | color: { |
| | | dark: form.foregroundColor, |
| | | light: form.backgroundColor, |
| | | }, |
| | | }); |
| | | } |
| | | |
| | | batchCodes.value.push({ |
| | | content, |
| | | url: codeUrl, |
| | | }); |
| | | } |
| | | const byteArray = new Uint8Array(byteNumbers) |
| | | |
| | | zip.file(`${code.content}.png`, byteArray) |
| | | }) |
| | | |
| | | const content = await zip.generateAsync({ type: 'blob' }) |
| | | const a = document.createElement('a') |
| | | a.href = URL.createObjectURL(content) |
| | | a.download = `æ¹é${form.type === 'qrcode' ? 'äºç»´ç ' : 'é²ä¼ªç '}_${new Date().getTime()}.zip` |
| | | document.body.appendChild(a) |
| | | a.click() |
| | | document.body.removeChild(a) |
| | | URL.revokeObjectURL(a.href) |
| | | |
| | | ElMessage.success('æ¹éä¸è½½å®æï¼') |
| | | } catch (error) { |
| | | console.error('æ¹éä¸è½½å¤±è´¥:', error) |
| | | ElMessage.error('æ¹éä¸è½½å¤±è´¥ï¼è¯·é个ä¸è½½') |
| | | } |
| | | } |
| | | |
| | | // æ¸
空æ¹éçæç»æ |
| | | const clearBatchCodes = () => { |
| | | batchCodes.value = [] |
| | | } |
| | | ElMessage.success(`æ¹éçæå®æï¼å
±çæ ${batchForm.quantity} 个ç `); |
| | | batchDialogVisible.value = false; |
| | | } catch (error) { |
| | | console.error("æ¹éçæå¤±è´¥:", error); |
| | | ElMessage.error("æ¹éçæå¤±è´¥ï¼" + error.message); |
| | | } finally { |
| | | generating.value = false; |
| | | } |
| | | }; |
| | | |
| | | // æ´é²æ¹æ³ç»ç¶ç»ä»¶ |
| | | defineExpose({ |
| | | generateCode, |
| | | downloadCode, |
| | | resetForm, |
| | | form |
| | | }) |
| | | // ä¸è½½å个æ¹éçæçç |
| | | const downloadSingleCode = code => { |
| | | const a = document.createElement("a"); |
| | | a.href = code.url; |
| | | a.download = `${code.content}.png`; |
| | | document.body.appendChild(a); |
| | | a.click(); |
| | | document.body.removeChild(a); |
| | | }; |
| | | |
| | | // ä¸è½½æææ¹éçæçç |
| | | const downloadAllCodes = async () => { |
| | | if (batchCodes.value.length === 0) { |
| | | ElMessage.warning("没æå¯ä¸è½½çç "); |
| | | return; |
| | | } |
| | | |
| | | try { |
| | | // 使ç¨JSZipæå
ä¸è½½ |
| | | const JSZip = await import("jszip"); |
| | | const zip = new JSZip.default(); |
| | | |
| | | batchCodes.value.forEach((code, index) => { |
| | | // å°base64转æ¢ä¸ºblob |
| | | const base64Data = code.url.split(",")[1]; |
| | | const byteCharacters = atob(base64Data); |
| | | const byteNumbers = new Array(byteCharacters.length); |
| | | for (let i = 0; i < byteCharacters.length; i++) { |
| | | byteNumbers[i] = byteCharacters.charCodeAt(i); |
| | | } |
| | | const byteArray = new Uint8Array(byteNumbers); |
| | | |
| | | zip.file(`${code.content}.png`, byteArray); |
| | | }); |
| | | |
| | | const content = await zip.generateAsync({ type: "blob" }); |
| | | const a = document.createElement("a"); |
| | | a.href = URL.createObjectURL(content); |
| | | a.download = `æ¹é${ |
| | | form.type === "qrcode" ? "äºç»´ç " : "é²ä¼ªç " |
| | | }_${new Date().getTime()}.zip`; |
| | | document.body.appendChild(a); |
| | | a.click(); |
| | | document.body.removeChild(a); |
| | | URL.revokeObjectURL(a.href); |
| | | |
| | | ElMessage.success("æ¹éä¸è½½å®æï¼"); |
| | | } catch (error) { |
| | | console.error("æ¹éä¸è½½å¤±è´¥:", error); |
| | | ElMessage.error("æ¹éä¸è½½å¤±è´¥ï¼è¯·é个ä¸è½½"); |
| | | } |
| | | }; |
| | | |
| | | // æ¸
空æ¹éçæç»æ |
| | | const clearBatchCodes = () => { |
| | | batchCodes.value = []; |
| | | }; |
| | | |
| | | // æ´é²æ¹æ³ç»ç¶ç»ä»¶ |
| | | defineExpose({ |
| | | generateCode, |
| | | downloadCode, |
| | | resetForm, |
| | | form, |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .qr-code-generator { |
| | | padding: 20px; |
| | | } |
| | | .qr-code-generator { |
| | | padding: 20px; |
| | | } |
| | | |
| | | .qr-form { |
| | | background: #f8f9fa; |
| | | padding: 20px; |
| | | border-radius: 8px; |
| | | margin-bottom: 20px; |
| | | } |
| | | .qr-form { |
| | | background: #f8f9fa; |
| | | padding: 20px; |
| | | border-radius: 8px; |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .code-display { |
| | | margin-top: 30px; |
| | | } |
| | | .code-display { |
| | | margin-top: 30px; |
| | | } |
| | | |
| | | .code-container { |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: flex-start; |
| | | gap: 40px; |
| | | margin: 20px 0; |
| | | } |
| | | |
| | | .code-image img { |
| | | border: 2px solid #e0e0e0; |
| | | border-radius: 8px; |
| | | box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); |
| | | } |
| | | |
| | | .code-info { |
| | | text-align: left; |
| | | min-width: 200px; |
| | | } |
| | | |
| | | .code-info p { |
| | | margin: 8px 0; |
| | | color: #666; |
| | | } |
| | | |
| | | .code-actions { |
| | | text-align: center; |
| | | margin: 20px 0; |
| | | } |
| | | |
| | | .code-actions .el-button { |
| | | margin: 0 10px; |
| | | } |
| | | |
| | | .batch-results { |
| | | margin-top: 30px; |
| | | } |
| | | |
| | | .batch-grid { |
| | | display: grid; |
| | | grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); |
| | | gap: 20px; |
| | | margin: 20px 0; |
| | | } |
| | | |
| | | .batch-item { |
| | | text-align: center; |
| | | padding: 15px; |
| | | border: 1px solid #e0e0e0; |
| | | border-radius: 8px; |
| | | background: #fff; |
| | | } |
| | | |
| | | .batch-item img { |
| | | width: 100px; |
| | | height: 100px; |
| | | margin-bottom: 10px; |
| | | } |
| | | |
| | | .batch-content { |
| | | font-size: 12px; |
| | | color: #666; |
| | | margin: 10px 0; |
| | | word-break: break-all; |
| | | } |
| | | |
| | | .batch-actions { |
| | | text-align: center; |
| | | margin: 20px 0; |
| | | } |
| | | |
| | | .batch-actions .el-button { |
| | | margin: 0 10px; |
| | | } |
| | | |
| | | @media (max-width: 768px) { |
| | | .code-container { |
| | | flex-direction: column; |
| | | align-items: center; |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: flex-start; |
| | | gap: 40px; |
| | | margin: 20px 0; |
| | | } |
| | | |
| | | |
| | | .code-image img { |
| | | border: 2px solid #e0e0e0; |
| | | border-radius: 8px; |
| | | box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); |
| | | } |
| | | |
| | | .code-info { |
| | | text-align: left; |
| | | min-width: 200px; |
| | | } |
| | | |
| | | .code-info p { |
| | | margin: 8px 0; |
| | | color: #666; |
| | | } |
| | | |
| | | .code-actions { |
| | | text-align: center; |
| | | margin: 20px 0; |
| | | } |
| | | |
| | | .code-actions .el-button { |
| | | margin: 0 10px; |
| | | } |
| | | |
| | | .batch-results { |
| | | margin-top: 30px; |
| | | } |
| | | |
| | | .batch-grid { |
| | | grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); |
| | | display: grid; |
| | | grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); |
| | | gap: 20px; |
| | | margin: 20px 0; |
| | | } |
| | | } |
| | | |
| | | .batch-item { |
| | | text-align: center; |
| | | padding: 15px; |
| | | border: 1px solid #e0e0e0; |
| | | border-radius: 8px; |
| | | background: #fff; |
| | | } |
| | | |
| | | .batch-item img { |
| | | width: 100px; |
| | | height: 100px; |
| | | margin-bottom: 10px; |
| | | } |
| | | |
| | | .batch-content { |
| | | font-size: 12px; |
| | | color: #666; |
| | | margin: 10px 0; |
| | | word-break: break-all; |
| | | } |
| | | |
| | | .batch-actions { |
| | | text-align: center; |
| | | margin: 20px 0; |
| | | } |
| | | |
| | | .batch-actions .el-button { |
| | | margin: 0 10px; |
| | | } |
| | | |
| | | @media (max-width: 768px) { |
| | | .code-container { |
| | | flex-direction: column; |
| | | align-items: center; |
| | | } |
| | | |
| | | .batch-grid { |
| | | grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); |
| | | } |
| | | } |
| | | </style> |
| | |
| | | <breadcrumb v-if="!settingsStore.topNav" id="breadcrumb-container" class="breadcrumb-container" />
|
| | | </div>
|
| | | <!-- <top-nav v-if="settingsStore.topNav" id="topmenu-container" class="topmenu-container" />-->
|
| | | <div class="center-menu">
|
| | | <span class="label">{{ userStore.currentFactoryName }}</span>
|
| | | <el-dropdown @command="handleFactoryChange" class="right-menu-item hover-effect" trigger="click">
|
| | | <div>
|
| | | <el-icon size="20">
|
| | | <Switch />
|
| | | </el-icon>
|
| | | </div>
|
| | | <template #dropdown>
|
| | | <el-dropdown-menu>
|
| | | <el-dropdown-item v-for="item in factoryList" :key="item.deptId" :command="item">
|
| | | {{ item.deptName }}
|
| | | </el-dropdown-item>
|
| | | </el-dropdown-menu>
|
| | | </template>
|
| | | </el-dropdown>
|
| | | </div>
|
| | | <div class="right-menu">
|
| | | <!-- æ¶æ¯éç¥ -->
|
| | | <el-popover
|
| | |
| | | import useAppStore from '@/store/modules/app'
|
| | | import useUserStore from '@/store/modules/user'
|
| | | import useSettingsStore from '@/store/modules/settings'
|
| | | import { userLoginFacotryList } from "@/api/system/user.js"
|
| | | import Cookies from "js-cookie";
|
| | | import { decrypt } from "@/utils/jsencrypt"
|
| | |
|
| | | const appStore = useAppStore()
|
| | | const userStore = useUserStore()
|
| | | const settingsStore = useSettingsStore()
|
| | | const factoryList = ref([])
|
| | | const notificationVisible = ref(false)
|
| | | const notificationCenterRef = ref(null)
|
| | | const unreadCount = ref(0)
|
| | |
| | | function toggleTheme() {
|
| | | settingsStore.toggleTheme()
|
| | | }
|
| | |
|
| | | function getUserLoginFacotryList() {
|
| | | if (userStore.id) {
|
| | | userLoginFacotryList({ userId: userStore.id }).then(res => {
|
| | | console.log('res', res)
|
| | | factoryList.value = res.data
|
| | | })
|
| | | } else {
|
| | | factoryList.value = []
|
| | | }
|
| | | }
|
| | |
|
| | | function handleFactoryChange(command) {
|
| | | console.log('command', command)
|
| | | handleLogin(command.deptId);
|
| | | }
|
| | |
|
| | | function handleLogin(currentFatoryId) {
|
| | | const loginForm = {
|
| | | username: Cookies.get("username"),
|
| | | password: Cookies.get("password") === undefined ? null : decrypt(Cookies.get("password")),
|
| | | currentFatoryId: currentFatoryId
|
| | | }
|
| | | userStore.loginCheckFactory(loginForm).then(res => {
|
| | | forceReload();
|
| | | }).catch((err) => {
|
| | | console.log(err)
|
| | | })
|
| | | }
|
| | | function forceReload() {
|
| | | const currentUrl = window.location.origin + window.location.pathname;
|
| | | const timestamp = new Date().getTime();
|
| | | window.location.href = `${currentUrl}?reload=${timestamp}`;
|
| | | }
|
| | |
|
| | | getUserLoginFacotryList();
|
| | |
|
| | | // æ¶æ¯éç¥ç¸å
³
|
| | | function handleUnreadCountChange(count) {
|
| | |
| | | position: relative;
|
| | | background: var(--navbar-bg);
|
| | | box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
|
| | |
|
| | | .center-menu {
|
| | | line-height: 50px;
|
| | | position: absolute;
|
| | | left: 50%;
|
| | | transform: translateX(-50%);
|
| | | display: flex;
|
| | | align-items: center;
|
| | |
|
| | | .label {
|
| | | font-weight: bold;
|
| | | font-size: 18px;
|
| | | color: #333333;
|
| | | margin-right: 10px;
|
| | | }
|
| | | }
|
| | |
|
| | | .hamburger-container {
|
| | | line-height: 46px;
|
| | |
| | | } |
| | | const params = { |
| | | consigneeId: consigneeId, |
| | | pageNum: pageNum.value, |
| | | pageSize: pageSize.value, |
| | | current: pageNum.value, |
| | | size: pageSize.value, |
| | | status: activeTab.value === 'read' ? 1 : 0 |
| | | } |
| | | const res = await listMessage(params) |
| | |
| | | import DictTag from "@/components/DictTag"; |
| | | // è¡¨æ ¼ç»ä»¶ |
| | | import PIMTable from "@/components/PIMTable/PIMTable.vue"; |
| | | // 页é¢å¤´é¨ç»ä»¶ |
| | | import PageHeader from "@/components/PageHeader/index.vue"; |
| | | |
| | | import { getToken } from "@/utils/auth"; |
| | | import { |
| | |
| | | app.component("RightToolbar", RightToolbar); |
| | | app.component("Editor", Editor); |
| | | app.component("PIMTable", PIMTable); |
| | | app.component("PageHeader", PageHeader); |
| | | |
| | | app.use(router); |
| | | app.use(store); |
| | |
| | | loginCheckFactory(userInfo) {
|
| | | const username = userInfo.username.trim()
|
| | | const password = userInfo.password
|
| | | const factoryId = userInfo.currentFatoryId
|
| | | return new Promise((resolve, reject) => {
|
| | | loginCheckFactory(username, password, factoryId).then(res => {
|
| | | loginCheckFactory(username, password).then(res => {
|
| | | setToken(res.token)
|
| | | this.token = res.token
|
| | | resolve()
|
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <el-dialog |
| | | v-model="visible" |
| | | title="éæ©äº§å" |
| | | width="900px" |
| | | destroy-on-close |
| | | :close-on-click-modal="false" |
| | | > |
| | | <el-form :inline="true" :model="query" class="mb-2"> |
| | | <el-form-item label="产å大类"> |
| | | <el-input |
| | | v-model="query.productName" |
| | | placeholder="è¾å
¥äº§å大类" |
| | | clearable |
| | | @keyup.enter="onSearch" |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="åå·åç§°"> |
| | | <el-input |
| | | v-model="query.model" |
| | | placeholder="è¾å
¥åå·åç§°" |
| | | clearable |
| | | @keyup.enter="onSearch" |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item> |
| | | <el-button type="primary" @click="onSearch">æç´¢</el-button> |
| | | <el-button @click="onReset">éç½®</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | |
| | | <!-- å表 --> |
| | | <el-table |
| | | v-loading="loading" |
| | | :data="tableData" |
| | | height="420" |
| | | highlight-current-row |
| | | row-key="id" |
| | | @selection-change="handleSelectionChange" |
| | | > |
| | | <el-table-column type="selection" width="55" /> |
| | | <el-table-column type="index" label="#" width="60"/> |
| | | <el-table-column prop="productName" label="产å大类" min-width="160"/> |
| | | <el-table-column prop="model" label="åå·åç§°" min-width="200"/> |
| | | <el-table-column prop="unit" label="åä½" min-width="160"/> |
| | | </el-table> |
| | | |
| | | <div class="mt-3 flex justify-end"> |
| | | <el-pagination |
| | | background |
| | | layout="total, sizes, prev, pager, next, jumper" |
| | | :total="total" |
| | | v-model:page-size="page.pageSize" |
| | | v-model:current-page="page.pageNum" |
| | | :page-sizes="[10, 20, 50, 100]" |
| | | @size-change="onPageChange" |
| | | @current-change="onPageChange" |
| | | /> |
| | | </div> |
| | | |
| | | <template #footer> |
| | | <el-button @click="close()">åæ¶</el-button> |
| | | <el-button type="primary" :disabled="multipleSelection.length === 0" @click="onConfirm"> |
| | | ç¡®å® |
| | | </el-button> |
| | | </template> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import {computed, onMounted, reactive, ref, watch} from "vue"; |
| | | import {ElMessage} from "element-plus"; |
| | | import {productModelList} from '@/api/basicData/productModel' |
| | | |
| | | export type ProductRow = { |
| | | id: number; |
| | | productName: string; |
| | | model: string; |
| | | unit?: string; |
| | | }; |
| | | |
| | | const props = defineProps<{ |
| | | modelValue: boolean; |
| | | }>(); |
| | | |
| | | const emit = defineEmits(['update:modelValue', 'confirm']); |
| | | |
| | | const visible = computed({ |
| | | get: () => props.modelValue, |
| | | set: (v) => emit("update:modelValue", v), |
| | | }); |
| | | |
| | | const query = reactive({ |
| | | productName: "", |
| | | model: "", |
| | | }); |
| | | |
| | | const page = reactive({ |
| | | pageNum: 1, |
| | | pageSize: 10, |
| | | }); |
| | | |
| | | const loading = ref(false); |
| | | const tableData = ref<ProductRow[]>([]); |
| | | const total = ref(0); |
| | | const multipleSelection = ref<ProductRow[]>([]) |
| | | |
| | | function close() { |
| | | visible.value = false; |
| | | } |
| | | |
| | | const handleSelectionChange = (val: ProductRow[]) => { |
| | | multipleSelection.value = val |
| | | } |
| | | |
| | | function onSearch() { |
| | | page.pageNum = 1; |
| | | loadData(); |
| | | } |
| | | |
| | | function onReset() { |
| | | query.productName = ""; |
| | | query.model = ""; |
| | | page.pageNum = 1; |
| | | loadData(); |
| | | } |
| | | |
| | | function onPageChange() { |
| | | loadData(); |
| | | } |
| | | |
| | | function onConfirm() { |
| | | if (multipleSelection.value.length === 0) { |
| | | ElMessage.warning("è¯·éæ©ä¸æ¡äº§å"); |
| | | return; |
| | | } |
| | | emit("confirm", multipleSelection.value); |
| | | close(); |
| | | } |
| | | |
| | | async function loadData() { |
| | | loading.value = true; |
| | | try { |
| | | multipleSelection.value = []; // 翻页/æç´¢åæ¸
ç©ºéæ©æ´ç¬¦å颿 |
| | | const res = await productModelList({ |
| | | productName: query.productName.trim(), |
| | | model: query.model.trim(), |
| | | current: page.pageNum, |
| | | size: page.pageSize, |
| | | }); |
| | | tableData.value = res.records; |
| | | total.value = res.total; |
| | | } finally { |
| | | loading.value = false; |
| | | } |
| | | } |
| | | |
| | | onMounted(() => { |
| | | loadData() |
| | | }) |
| | | </script> |
| | |
| | | :data="list" |
| | | @node-click="handleNodeClick" |
| | | :expand-on-click-node="false" |
| | | default-expand-all |
| | | :default-expanded-keys="expandedKeys" |
| | | :draggable="true" |
| | | :filter-node-method="filterNode" |
| | | :props="{ children: 'children', label: 'label' }" |
| | | highlight-current |
| | |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="24"> |
| | | <el-form-item label="ç³è¯·é¨é¨ï¼" prop="approveDeptId"> |
| | | <el-form-item label="ç³è¯·é¨é¨ï¼"> |
| | | <el-select |
| | | disabled |
| | | v-model="form.approveDeptId" |
| | |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-row v-if="!isQuotationApproval"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="审æ¹äºç±ï¼" prop="approveReason"> |
| | | <el-input v-model="form.approveReason" placeholder="请è¾å
¥" clearable type="textarea" disabled/> |
| | |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | |
| | | <!-- æ¥ä»·å®¡æ¹ï¼å±ç¤ºæ¥ä»·è¯¦æ
ï¼å¤ç¨é宿¥ä»·âæ¥ç详æ
å¯¹è¯æ¡âå
å®¹ç»æï¼ --> |
| | | <div v-if="isQuotationApproval" style="margin: 10px 0 18px;"> |
| | | <el-divider content-position="left">æ¥ä»·è¯¦æ
</el-divider> |
| | | <el-skeleton :loading="quotationLoading" animated> |
| | | <template #template> |
| | | <el-skeleton-item variant="h3" style="width: 30%" /> |
| | | <el-skeleton-item variant="text" style="width: 100%" /> |
| | | <el-skeleton-item variant="text" style="width: 100%" /> |
| | | </template> |
| | | <template #default> |
| | | <el-empty v-if="!currentQuotation || !currentQuotation.quotationNo" description="æªæ¥è¯¢å°å¯¹åºæ¥ä»·è¯¦æ
" /> |
| | | <template v-else> |
| | | <el-descriptions :column="2" border> |
| | | <el-descriptions-item label="æ¥ä»·åå·">{{ currentQuotation.quotationNo }}</el-descriptions-item> |
| | | <el-descriptions-item label="客æ·åç§°">{{ currentQuotation.customer }}</el-descriptions-item> |
| | | <el-descriptions-item label="ä¸å¡å">{{ currentQuotation.salesperson }}</el-descriptions-item> |
| | | <el-descriptions-item label="æ¥ä»·æ¥æ">{{ currentQuotation.quotationDate }}</el-descriptions-item> |
| | | <el-descriptions-item label="æææè³">{{ currentQuotation.validDate }}</el-descriptions-item> |
| | | <el-descriptions-item label="仿¬¾æ¹å¼">{{ currentQuotation.paymentMethod }}</el-descriptions-item> |
| | | <el-descriptions-item label="æ¥ä»·æ»é¢" :span="2"> |
| | | <span style="font-size: 18px; color: #e6a23c; font-weight: bold;"> |
| | | ¥{{ Number(currentQuotation.totalAmount ?? 0).toFixed(2) }} |
| | | </span> |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | |
| | | <div style="margin-top: 20px;"> |
| | | <h4>产åæç»</h4> |
| | | <el-table :data="currentQuotation.products || []" border style="width: 100%"> |
| | | <el-table-column prop="product" label="产ååç§°" /> |
| | | <el-table-column prop="specification" label="è§æ ¼åå·" /> |
| | | <el-table-column prop="unit" label="åä½" /> |
| | | <el-table-column prop="unitPrice" label="åä»·"> |
| | | <template #default="scope">Â¥{{ Number(scope.row.unitPrice ?? 0).toFixed(2) }}</template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | |
| | | <div v-if="currentQuotation.remark" style="margin-top: 20px;"> |
| | | <h4>夿³¨</h4> |
| | | <p>{{ currentQuotation.remark }}</p> |
| | | </div> |
| | | </template> |
| | | </template> |
| | | </el-skeleton> |
| | | </div> |
| | | |
| | | <el-form :model="{ activities }" ref="formRef" label-position="top"> |
| | | <el-steps :active="getActiveStep()" finish-status="success" process-status="process" align-center direction="vertical"> |
| | | <el-step |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { getCurrentInstance, reactive, ref, toRefs } from "vue"; |
| | | import { computed, getCurrentInstance, nextTick, reactive, ref, toRefs } from "vue"; |
| | | import { |
| | | approveProcessDetails, |
| | | getDept, |
| | |
| | | import useUserStore from "@/store/modules/user.js"; |
| | | import {userListNoPageByTenantId} from "@/api/system/user.js"; |
| | | import { WarningFilled, Edit, Check, MoreFilled } from '@element-plus/icons-vue' |
| | | import { getQuotationList } from "@/api/salesManagement/salesQuotation.js"; |
| | | const emit = defineEmits(['close']) |
| | | const { proxy } = getCurrentInstance() |
| | | |
| | | const props = defineProps({ |
| | | approveType: { |
| | | type: [Number, String], |
| | | default: 0 |
| | | } |
| | | }) |
| | | |
| | | const dialogFormVisible = ref(false); |
| | | const operationType = ref('') |
| | |
| | | const userStore = useUserStore() |
| | | const productOptions = ref([]); |
| | | const userList = ref([]) |
| | | const quotationLoading = ref(false) |
| | | const currentQuotation = ref({}) |
| | | const isQuotationApproval = computed(() => Number(props.approveType) === 6) |
| | | |
| | | const data = reactive({ |
| | | form: { |
| | | approveTime: "", |
| | |
| | | const openDialog = (type, row) => { |
| | | operationType.value = type; |
| | | dialogFormVisible.value = true; |
| | | currentQuotation.value = {} |
| | | userListNoPageByTenantId().then((res) => { |
| | | userList.value = res.data; |
| | | }); |
| | | form.value = {...row} |
| | | getProductOptions() |
| | | // ç«å³æ¸
é¤è¡¨åéªè¯ç¶æï¼å ä¸ºåæ®µæ¯disabledçï¼ä¸éè¦éªè¯ï¼ |
| | | nextTick(() => { |
| | | if (formRef.value) { |
| | | formRef.value.clearValidate(); |
| | | } |
| | | }); |
| | | // ç¡®ä¿é项å è½½å®æååå¹é
å¼ç±»å |
| | | getProductOptions().then(() => { |
| | | // ç¡®ä¿å¼ç±»åå¹é
ï¼å¦æé项已å è½½ï¼ |
| | | if (productOptions.value.length > 0 && form.value.approveDeptId) { |
| | | const matchedOption = productOptions.value.find(opt => |
| | | opt.deptId == form.value.approveDeptId || |
| | | String(opt.deptId) === String(form.value.approveDeptId) |
| | | ); |
| | | if (matchedOption) { |
| | | form.value.approveDeptId = matchedOption.deptId; |
| | | } |
| | | } |
| | | // 忬¡æ¸
é¤éªè¯ï¼ç¡®ä¿é项å è½½åå¼å¹é
æ£ç¡® |
| | | nextTick(() => { |
| | | if (formRef.value) { |
| | | formRef.value.clearValidate(); |
| | | } |
| | | }); |
| | | }); |
| | | |
| | | // æ¥ä»·å®¡æ¹ï¼ç¨å®¡æ¹äºç±å段æ¿è½½çâæ¥ä»·åå·â廿¥æ¥ä»·å表 |
| | | if (isQuotationApproval.value) { |
| | | const quotationNo = row?.approveReason; |
| | | if (quotationNo) { |
| | | quotationLoading.value = true |
| | | getQuotationList({ quotationNo }).then((res) => { |
| | | const records = res?.data?.records || [] |
| | | currentQuotation.value = records[0] || {} |
| | | }).finally(() => { |
| | | quotationLoading.value = false |
| | | }) |
| | | } |
| | | } |
| | | |
| | | approveProcessDetails(row.approveId).then((res) => { |
| | | activities.value = res.data |
| | | // å¢å isApprovalåæ®µ |
| | |
| | | }) |
| | | } |
| | | const getProductOptions = () => { |
| | | getDept().then((res) => { |
| | | return getDept().then((res) => { |
| | | productOptions.value = res.data; |
| | | }); |
| | | }; |
| | | // æäº¤å®¡æ¹ |
| | | const submitForm = (status) => { |
| | | const filteredActivities = activities.value.filter(activity => activity.isShen); |
| | | filteredActivities[0].approveNodeStatus = status; |
| | | if (!filteredActivities || filteredActivities.length === 0) { |
| | | proxy.$modal.msgError("æªæ¾å°å¾
审æ¹çèç¹"); |
| | | return; |
| | | } |
| | | const currentActivity = filteredActivities[0]; |
| | | if (!currentActivity) { |
| | | proxy.$modal.msgError("æªæ¾å°å¾
审æ¹çèç¹"); |
| | | return; |
| | | } |
| | | currentActivity.approveNodeStatus = status; |
| | | // 夿æ¯å¦ä¸ºæå䏿¥ |
| | | const isLast = activities.value.findIndex(a => a.isShen) === activities.value.length-1; |
| | | updateApproveNode({ ...filteredActivities[0], isLast }).then(() => { |
| | | updateApproveNode({ ...currentActivity, isLast }).then(() => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeDia(); |
| | | }); |
| | |
| | | const closeDia = () => { |
| | | proxy.resetForm("formRef"); |
| | | dialogFormVisible.value = false; |
| | | quotationLoading.value = false |
| | | currentQuotation.value = {} |
| | | emit('close') |
| | | }; |
| | | defineExpose({ |
| | |
| | | <el-row> |
| | | <el-col :span="24"> |
| | | <el-form-item label="ç³è¯·é¨é¨ï¼" prop="approveDeptName"> |
| | | <el-input v-model="form.approveDeptName" placeholder="请è¾å
¥" clearable/> |
| | | <!-- <el-select--> |
| | | <!-- disabled--> |
| | | <!-- v-model="form.approveDeptId"--> |
| | | <!-- placeholder="éæ©é¨é¨"--> |
| | | <!-- >--> |
| | | <!-- <el-option--> |
| | | <!-- v-for="user in productOptions"--> |
| | | <!-- :key="user.deptId"--> |
| | | <!-- :label="user.deptName"--> |
| | | <!-- :value="user.deptId"--> |
| | | <!-- />--> |
| | | <!-- </el-select>--> |
| | | <!-- <el-input v-model="form.approveDeptName" placeholder="请è¾å
¥" clearable/>--> |
| | | <el-select |
| | | v-model="form.approveDeptId" |
| | | placeholder="éæ©é¨é¨" |
| | | @change="handleDeptChange" |
| | | > |
| | | <el-option |
| | | v-for="user in productOptions" |
| | | :key="user.deptId" |
| | | :label="user.deptName" |
| | | :value="user.deptId" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | |
| | | const emit = defineEmits(['close']) |
| | | import useUserStore from "@/store/modules/user"; |
| | | import { getCurrentDate } from "@/utils/index.js"; |
| | | import log from "@/views/monitor/job/log.vue"; |
| | | const userStore = useUserStore(); |
| | | |
| | | const dialogFormVisible = ref(false); |
| | |
| | | function removeApproverNode(index) { |
| | | approverNodes.value.splice(index, 1) |
| | | } |
| | | |
| | | // å¤çé¨é¨éæ©åå |
| | | const handleDeptChange = (deptId) => { |
| | | if (deptId) { |
| | | const selectedDept = productOptions.value.find(dept => dept.deptId === deptId); |
| | | if (selectedDept) { |
| | | form.value.approveDeptName = selectedDept.deptName; |
| | | } |
| | | } else { |
| | | form.value.approveDeptName = ''; |
| | | } |
| | | }; |
| | | // æå¼å¼¹æ¡ |
| | | const openDialog = (type, row) => { |
| | | operationType.value = type; |
| | |
| | | userListNoPageByTenantId().then((res) => { |
| | | userList.value = res.data; |
| | | }); |
| | | getProductOptions(); |
| | | form.value = {} |
| | | approverNodes.value = [ |
| | | { id: 1, userId: null } |
| | |
| | | |
| | | // è·åå½åç¨æ·ä¿¡æ¯å¹¶è®¾ç½®é¨é¨ID |
| | | form.value.approveDeptId = userStore.currentDeptId |
| | | |
| | | // å è½½é¨é¨é项ï¼å¹¶å¨å è½½å®æå设置é¨é¨åç§° |
| | | getProductOptions(); |
| | | if (operationType.value === 'edit') { |
| | | fileList.value = row.commonFileList |
| | | form.value.tempFileIds = fileList.value.map(file => file.id) |
| | |
| | | } |
| | | } |
| | | const getProductOptions = () => { |
| | | getDept().then((res) => { |
| | | return getDept().then((res) => { |
| | | productOptions.value = res.data; |
| | | // 妿已æé¨é¨IDï¼èªå¨è®¾ç½®é¨é¨åç§°ï¼ç¨äºéªè¯ï¼ |
| | | if (form.value.approveDeptId && productOptions.value.length > 0) { |
| | | const matchedDept = productOptions.value.find(dept => |
| | | dept.deptId == form.value.approveDeptId || |
| | | String(dept.deptId) === String(form.value.approveDeptId) |
| | | ); |
| | | if (matchedDept) { |
| | | form.value.approveDeptName = matchedDept.deptName; |
| | | } |
| | | } |
| | | }); |
| | | }; |
| | | function convertIdToValue(data) { |
| | |
| | | > |
| | | </div> |
| | | <div> |
| | | <el-button type="primary" @click="openForm('add')">æ°å¢</el-button> |
| | | <el-button type="primary" @click="openForm('add')" v-if="currentApproveType !== 6">æ°å¢</el-button> |
| | | <el-button @click="handleOut">导åº</el-button> |
| | | <el-button type="danger" plain @click="handleDelete">å é¤</el-button> |
| | | </div> |
| | |
| | | ></PIMTable> |
| | | </div> |
| | | <info-form-dia ref="infoFormDia" @close="handleQuery" :approveType="currentApproveType"></info-form-dia> |
| | | <approval-dia ref="approvalDia" @close="handleQuery"></approval-dia> |
| | | <approval-dia ref="approvalDia" @close="handleQuery" :approveType="currentApproveType"></approval-dia> |
| | | <FileList ref="fileListRef" /> |
| | | </div> |
| | | </template> |
| | |
| | | const tableColumnCopy = computed(() => { |
| | | const isLeaveType = currentApproveType.value === 2; // 请å管ç |
| | | const isReimburseType = currentApproveType.value === 4; // æ¥é管ç |
| | | const isQuotationType = currentApproveType.value === 6; // æ¥ä»·å®¡æ¹ |
| | | |
| | | // åºç¡åé
ç½® |
| | | const baseColumns = [ |
| | |
| | | width: 220 |
| | | }, |
| | | { |
| | | label: "审æ¹äºç±", |
| | | label: isQuotationType ? "æ¥ä»·åå·" : "审æ¹äºç±", |
| | | prop: "approveReason", |
| | | width: 200 |
| | | }, |
| | |
| | | clickFun: (row) => { |
| | | openForm("edit", row); |
| | | }, |
| | | disabled: (row) => row.approveStatus == 2 || row.approveStatus == 1 || row.approveStatus == 4 |
| | | disabled: (row) => currentApproveType.value === 6 || row.approveStatus == 2 || row.approveStatus == 1 || row.approveStatus == 4 |
| | | }, |
| | | { |
| | | name: "å®¡æ ¸", |
| | |
| | | getEmployeeDetail |
| | | } from '@/api/collaborativeApproval/enterpriseBook.js' |
| | | import { getUserProfile } from '@/api/system/user.js' |
| | | import {staffJoinListPage} from "@/api/personnelManagement/onboarding.js"; |
| | | import { |
| | | changeUserStatus, |
| | | listUser, |
| | |
| | | addUser, |
| | | deptTreeSelect, |
| | | } from "@/api/system/user"; |
| | | import {staffOnJobListPage} from "@/api/personnelManagement/staffOnJob.js"; |
| | | |
| | | // æ ç¾é¡µç¶æ |
| | | const activeTab = ref('personal') |
| | |
| | | } |
| | | //è·ååå·¥å表 |
| | | const getEmployeeList = async () => { |
| | | staffJoinListPage(publicSearch.value).then(res => { |
| | | staffOnJobListPage(Object.assign({current: -1, size: -1},publicSearch.value)).then(res => { |
| | | console.log(res.data.records) |
| | | EmployeeList.value = res.data.records |
| | | }).catch(err => {}) |
| | |
| | | // è·ååä½é讯å½å表 |
| | | const getCompanyContactsList = async () => { |
| | | loading.value = true |
| | | staffJoinListPage(companySearch.value).then(res => { |
| | | staffOnJobListPage(Object.assign({current: -1, size: -1},companySearch.value)).then(res => { |
| | | // console.log(res.data.records) |
| | | companyContacts.value = res.data.records |
| | | }).catch(err => {}) |
| | |
| | | }; |
| | | |
| | | if (row.id) { |
| | | // ç¼è¾æ¨¡å¼ - å
å é¤åæ·»å ï¼å ä¸ºåªæ add å del æ¥å£ï¼ |
| | | delNoticeType(row.id).then(res => { |
| | | if (res.code === 200) { |
| | | addNoticeType(data).then(addRes => { |
| | | if (addRes.code === 200) { |
| | | ElMessage.success('ç¼è¾æå'); |
| | | row.editing = false; |
| | | delete row.originalNoticeType; |
| | | fetchNoticeTypeList().then(() => { |
| | | // 妿å½åéä¸çç±»å被ç¼è¾ï¼éè¦éæ°è·åæ°æ® |
| | | if (activeNoticeTypeTab.value === String(row.id)) { |
| | | fetchNoticesByType(addRes.data?.id || row.id); |
| | | } |
| | | }); |
| | | } |
| | | }); |
| | | } |
| | | }); |
| | | } else { |
| | | // æ°å¢æ¨¡å¼ |
| | | addNoticeType(data).then(res => { |
| | | if (res.code === 200) { |
| | | ElMessage.success('æ°å¢æå'); |
| | | row.editing = false; |
| | | fetchNoticeTypeList(); |
| | | } |
| | | }); |
| | | // ç¼è¾æ¨¡å¼ - ä¼ å
¥id |
| | | data.id = row.id; |
| | | } |
| | | |
| | | addNoticeType(data).then(res => { |
| | | if (res.code === 200) { |
| | | ElMessage.success(row.id ? 'ç¼è¾æå' : 'æ°å¢æå'); |
| | | row.editing = false; |
| | | delete row.originalNoticeType; |
| | | fetchNoticeTypeList().then(() => { |
| | | // 妿å½åéä¸çç±»å被ç¼è¾ï¼éè¦éæ°è·åæ°æ® |
| | | if (row.id && activeNoticeTypeTab.value === String(row.id)) { |
| | | fetchNoticesByType(res.data?.id || row.id); |
| | | } |
| | | }); |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | const handleDeleteNoticeType = (row) => { |
| | |
| | | color: #606266; |
| | | line-height: 1.6; |
| | | font-size: 14px; |
| | | word-break: break-all; |
| | | white-space: pre-wrap; |
| | | overflow-wrap: break-word; |
| | | } |
| | | |
| | | .card-footer { |
| | |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import PIMTable from "@/components/PIMTable/PIMTable.vue"; |
| | | import { userListNoPageByTenantId } from "@/api/system/user.js"; |
| | | import { staffOnJobListPage } from "@/api/personnelManagement/employeeRecord.js"; |
| | | import { staffOnJobListPage } from "@/api/personnelManagement/staffOnJob.js"; |
| | | import { listNotification, addNotification, updateNotification, delNotification,addOnlineMeeting,addFileSharing } from "@/api/collaborativeApproval/notificationManagement.js"; |
| | | import { id } from "element-plus/es/locales.mjs"; |
| | | |
| | |
| | | <el-option |
| | | v-for="person in employees" |
| | | :key="person.id" |
| | | :label="`${person.staffName} (${person.postJob})`" |
| | | :label="`${person.staffName} (${person.postName})`" |
| | | :value="person.id" |
| | | /> |
| | | </el-select> |
| | |
| | | import {ElMessage} from 'element-plus' |
| | | import {Plus, Document, Promotion, Bell} from '@element-plus/icons-vue' |
| | | import {getRoomEnum, saveMeetingApplication} from '@/api/collaborativeApproval/meeting.js' |
| | | import {getStaffOnJob} from "@/api/personnelManagement/onboarding.js"; |
| | | import {staffOnJobListPage} from "@/api/personnelManagement/staffOnJob.js"; |
| | | |
| | | // å½åç³è¯·ç±»å |
| | | const currentType = ref('department') // approval: å®¡æ¹æµç¨, department: é¨é¨çº§, notification: éç¥åå¸ |
| | |
| | | getRoomEnum().then(res => { |
| | | meetingRooms.value = res.data |
| | | }) |
| | | getStaffOnJob().then(res => { |
| | | employees.value = res.data.sort((a, b) => a.postJob.localeCompare(b.postJob)) |
| | | staffOnJobListPage({ |
| | | current: -1, |
| | | size: -1, |
| | | staffState: 1 |
| | | }).then(res => { |
| | | employees.value = res.data.records.sort((a, b) => a.postName.localeCompare(b.postName)) |
| | | }) |
| | | }) |
| | | </script> |
| | |
| | | import {ElMessage, ElMessageBox} from 'element-plus' |
| | | import Pagination from '@/components/Pagination/index.vue' |
| | | import {getRoomEnum, getExamineList,saveMeetingApplication} from '@/api/collaborativeApproval/meeting.js' |
| | | import {getStaffOnJob} from "@/api/personnelManagement/onboarding.js"; |
| | | import dayjs from "dayjs"; |
| | | import {staffOnJobListPage} from "@/api/personnelManagement/staffOnJob.js"; |
| | | |
| | | // æ°æ®å表å è½½ç¶æ |
| | | const loading = ref(false) |
| | |
| | | it.participants = staffList.value.filter(staff => staffs.some(id=>id === staff.id)).map(staff => { |
| | | return { |
| | | id: staff.id, |
| | | name: `${staff.staffName}(${staff.postJob})` |
| | | name: `${staff.staffName}(${staff.postName})` |
| | | } |
| | | }) |
| | | |
| | |
| | | |
| | | // 页é¢å è½½æ¶è·åæ°æ® |
| | | onMounted(async () => { |
| | | const [resp1, resp2]= await Promise.all([getRoomEnum(), getStaffOnJob()]) |
| | | const [resp1, resp2]= await Promise.all([getRoomEnum(), staffOnJobListPage({current: -1, size: -1, staffState: 1})]) |
| | | roomEnum.value = resp1.data |
| | | staffList.value = resp2.data |
| | | staffList.value = resp2.data.records |
| | | |
| | | await getList() |
| | | }) |
| | |
| | | import {ElMessage, ElMessageBox} from 'element-plus' |
| | | import Pagination from '@/components/Pagination/index.vue' |
| | | import {getRoomEnum, getMeetingPublish,saveMeetingApplication} from '@/api/collaborativeApproval/meeting.js' |
| | | import {getStaffOnJob} from "@/api/personnelManagement/onboarding.js"; |
| | | import dayjs from "dayjs"; |
| | | import {staffOnJobListPage} from "@/api/personnelManagement/staffOnJob.js"; |
| | | |
| | | // æ°æ®å表å è½½ç¶æ |
| | | const loading = ref(false) |
| | |
| | | it.participants = staffList.value.filter(staff => staffs.some(id=>id === staff.id)).map(staff => { |
| | | return { |
| | | id: staff.id, |
| | | name: `${staff.staffName}(${staff.postJob})` |
| | | name: `${staff.staffName}(${staff.postName})` |
| | | } |
| | | }) |
| | | |
| | |
| | | |
| | | // 页é¢å è½½æ¶è·åæ°æ® |
| | | onMounted(async () => { |
| | | const [resp1, resp2]= await Promise.all([getRoomEnum(), getStaffOnJob()]) |
| | | const [resp1, resp2]= await Promise.all([getRoomEnum(), staffOnJobListPage({current: -1, size: -1, staffState: 1})]) |
| | | roomEnum.value = resp1.data |
| | | staffList.value = resp2.data |
| | | staffList.value = resp2.data.records |
| | | |
| | | await getList() |
| | | }) |
| | |
| | | import Pagination from '@/components/Pagination/index.vue' |
| | | import Editor from '@/components/Editor/index.vue' |
| | | import { getRoomEnum, getMeetingPublish ,getMeetingMinutesByMeetingId,saveMeetingMinutes} from '@/api/collaborativeApproval/meeting.js' |
| | | import { getStaffOnJob } from "@/api/personnelManagement/onboarding.js" |
| | | import dayjs from "dayjs" |
| | | import {staffOnJobListPage} from "@/api/personnelManagement/staffOnJob.js"; |
| | | |
| | | // æ°æ®å表å è½½ç¶æ |
| | | const loading = ref(false) |
| | |
| | | it.participants = staffList.value.filter(staff => staffs.some(id => id === staff.id)).map(staff => { |
| | | return { |
| | | id: staff.id, |
| | | name: `${staff.staffName}(${staff.postJob})` |
| | | name: `${staff.staffName}(${staff.postName})` |
| | | } |
| | | }) |
| | | |
| | |
| | | |
| | | // 页é¢å è½½æ¶è·åæ°æ® |
| | | onMounted(async () => { |
| | | const [resp1, resp2] = await Promise.all([getRoomEnum(), getStaffOnJob()]) |
| | | const [resp1, resp2] = await Promise.all([getRoomEnum(), staffOnJobListPage({current: -1, size: -1, staffState: 1})]) |
| | | roomEnum.value = resp1.data |
| | | staffList.value = resp2.data |
| | | staffList.value = resp2.data.records |
| | | |
| | | await getList() |
| | | }) |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | |
| | | <!-- è§ç« å¶åº¦ç®¡ç--> |
| | | <el-card class="box-card"> |
| | | <template #header> |
| | | <div class="card-header"> |
| | | <span>è§ç« å¶åº¦åå¸</span> |
| | | </div> |
| | | <!-- è§ç« å¶åº¦ç®¡ç--> |
| | | <el-card class="box-card"> |
| | | <template #header> |
| | | <div class="card-header"> |
| | | <span>è§ç« å¶åº¦åå¸</span> |
| | | </div> |
| | | </template> |
| | | <div class="tab-content"> |
| | | <el-row :gutter="20" |
| | | class="mb-20"> |
| | | <span class="ml-10">å¶åº¦æ é¢ï¼</span> |
| | | <el-col :span="6"> |
| | | <el-input v-model="regulationSearchForm.title" |
| | | placeholder="请è¾å
¥å¶åº¦æ é¢" |
| | | clearable /> |
| | | </el-col> |
| | | <span class="search_title">å¶åº¦åç±»ï¼</span> |
| | | <el-col :span="4"> |
| | | <el-select v-model="regulationSearchForm.category" |
| | | placeholder="å¶åº¦åç±»" |
| | | clearable> |
| | | <el-option label="人äºå¶åº¦" |
| | | value="hr" /> |
| | | <el-option label="è´¢å¡å¶åº¦" |
| | | value="finance" /> |
| | | <el-option label="å®å
¨å¶åº¦" |
| | | value="safety" /> |
| | | <el-option label="ææ¯å¶åº¦" |
| | | value="tech" /> |
| | | </el-select> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-button type="primary" |
| | | @click="searchRegulations">æç´¢</el-button> |
| | | <el-button @click="resetRegulationSearch">éç½®</el-button> |
| | | <el-button @click="handleExport">导åº</el-button> |
| | | <el-button type="success" |
| | | @click="handleAdd"> |
| | | åå¸å¶åº¦ |
| | | </el-button> |
| | | </el-col> |
| | | </el-row> |
| | | <el-table :data="regulations" |
| | | border |
| | | v-loading="tableLoading" |
| | | style="width: 100%"> |
| | | <el-table-column prop="regulationNum" |
| | | label="å¶åº¦ç¼å·" |
| | | width="120" /> |
| | | <el-table-column prop="title" |
| | | label="å¶åº¦æ é¢" |
| | | min-width="150" /> |
| | | <el-table-column prop="category" |
| | | label="åç±»" |
| | | width="120"> |
| | | <template #default="scope"> |
| | | <el-tag>{{ getCategoryText(scope.row.category) }}</el-tag> |
| | | </template> |
| | | <div class="tab-content"> |
| | | <el-row :gutter="20" class="mb-20"> |
| | | <span class="ml-10">å¶åº¦æ é¢ï¼</span> |
| | | <el-col :span="6"> |
| | | <el-input v-model="regulationSearchForm.title" placeholder="请è¾å
¥å¶åº¦æ é¢" clearable /> |
| | | </el-col> |
| | | <span class="search_title">å¶åº¦åç±»ï¼</span> |
| | | <el-col :span="4"> |
| | | <el-select v-model="regulationSearchForm.category" placeholder="å¶åº¦åç±»" clearable> |
| | | <el-option label="人äºå¶åº¦" value="hr" /> |
| | | <el-option label="è´¢å¡å¶åº¦" value="finance" /> |
| | | <el-option label="å®å
¨å¶åº¦" value="safety" /> |
| | | <el-option label="ææ¯å¶åº¦" value="tech" /> |
| | | </el-select> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-button type="primary" @click="searchRegulations">æç´¢</el-button> |
| | | <el-button @click="resetRegulationSearch">éç½®</el-button> |
| | | <el-button @click="handleExport">导åº</el-button> |
| | | <el-button type="success" @click="handleAdd"> |
| | | åå¸å¶åº¦ |
| | | </el-button> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-table :data="regulations" border v-loading="tableLoading" style="width: 100%"> |
| | | <el-table-column prop="regulationNum" label="å¶åº¦ç¼å·" width="120" /> |
| | | <el-table-column prop="title" label="å¶åº¦æ é¢" min-width="150" /> |
| | | <el-table-column prop="category" label="åç±»" width="120"> |
| | | <template #default="scope"> |
| | | <el-tag>{{ getCategoryText(scope.row.category) }}</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="version" label="çæ¬" width="120" /> |
| | | <el-table-column prop="createUserName" label="åå¸äºº" width="120" /> |
| | | <el-table-column prop="createTime" label="å叿¶é´" width="180" /> |
| | | <el-table-column prop="status" label="ç¶æ" width="100"> |
| | | <template #default="scope"> |
| | | <el-tag :type="scope.row.status === 'active' ? 'success' : 'info'"> |
| | | {{ scope.row.status === 'active' ? 'çæä¸' : 'å·²åºæ¢' }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="readCount" label="已读人æ°" width="100" /> |
| | | <el-table-column label="æä½" width="320" fixed="right"> |
| | | <template #default="scope"> |
| | | <el-button link @click="viewRegulation(scope.row)">æ¥ç</el-button> |
| | | <el-button link type="primary" @click="handleEdit(scope.row)">ç¼è¾</el-button> |
| | | <el-button link type="danger" @click="repealEdit(scope.row)">åºå¼</el-button> |
| | | <el-button link type="success" @click="viewVersionHistory(scope.row)">çæ¬åå²</el-button> |
| | | <el-button link type="warning" @click="viewReadStatus(scope.row)">é
è¯»ç¶æ</el-button> |
| | | <el-button link type="primary" @click="openFileDialog(scope.row)">éä»¶</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </el-card> |
| | | |
| | | </el-table-column> |
| | | <el-table-column prop="version" |
| | | label="çæ¬" |
| | | width="120" /> |
| | | <el-table-column prop="createUserName" |
| | | label="åå¸äºº" |
| | | width="120" /> |
| | | <el-table-column prop="createTime" |
| | | label="å叿¶é´" |
| | | width="180" /> |
| | | <el-table-column prop="status" |
| | | label="ç¶æ" |
| | | width="100"> |
| | | <template #default="scope"> |
| | | <el-tag :type="scope.row.status === 'active' ? 'success' : 'info'"> |
| | | {{ scope.row.status === 'active' ? 'çæä¸' : 'å·²åºæ¢' }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="readCount" |
| | | label="已读人æ°" |
| | | width="100" /> |
| | | <el-table-column label="æä½" |
| | | width="320" |
| | | fixed="right"> |
| | | <template #default="scope"> |
| | | <el-button link |
| | | @click="viewRegulation(scope.row)">æ¥ç</el-button> |
| | | <el-button link |
| | | type="primary" |
| | | @click="handleEdit(scope.row)">ç¼è¾</el-button> |
| | | <el-button link |
| | | type="danger" |
| | | @click="repealEdit(scope.row)">åºå¼</el-button> |
| | | <el-button link |
| | | type="success" |
| | | @click="viewVersionHistory(scope.row)">çæ¬åå²</el-button> |
| | | <!-- <el-button link type="warning" @click="viewReadStatus(scope.row)">é
è¯»ç¶æ</el-button> --> |
| | | <el-button link |
| | | type="primary" |
| | | @click="openFileDialog(scope.row)">éä»¶</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </el-card> |
| | | <!-- ç¨å°ç³è¯·å¯¹è¯æ¡ï¼å·²ç§»é¤ï¼ --> |
| | | |
| | | <!-- è§ç« å¶åº¦åå¸å¯¹è¯æ¡ --> |
| | | <el-dialog v-model="showRegulationDialog" :title="operationType === 'add' ? 'åå¸å¶åº¦' : 'ç¼è¾å¶åº¦'" width="800px"> |
| | | <el-form :model="regulationForm" :rules="regulationRules" ref="regulationFormRef" label-width="100px"> |
| | | <el-form-item label="å¶åº¦ç¼å·" prop="regulationNum"> |
| | | <el-input v-model="regulationForm.regulationNum" placeholder="请è¾å
¥å¶åº¦ç¼å·" /> |
| | | <el-dialog v-model="showRegulationDialog" |
| | | :title="operationType === 'add' ? 'åå¸å¶åº¦' : 'ç¼è¾å¶åº¦'" |
| | | width="800px"> |
| | | <el-form :model="regulationForm" |
| | | :rules="regulationRules" |
| | | ref="regulationFormRef" |
| | | label-width="100px"> |
| | | <el-form-item label="å¶åº¦ç¼å·" |
| | | prop="regulationNum"> |
| | | <el-input v-model="regulationForm.regulationNum" |
| | | placeholder="请è¾å
¥å¶åº¦ç¼å·" /> |
| | | </el-form-item> |
| | | <el-form-item label="å¶åº¦æ é¢" prop="title"> |
| | | <el-input v-model="regulationForm.title" placeholder="请è¾å
¥å¶åº¦æ é¢" /> |
| | | <el-form-item label="å¶åº¦æ é¢" |
| | | prop="title"> |
| | | <el-input v-model="regulationForm.title" |
| | | placeholder="请è¾å
¥å¶åº¦æ é¢" /> |
| | | </el-form-item> |
| | | <el-form-item label="å¶åº¦åç±»" prop="category"> |
| | | <el-select v-model="regulationForm.category" placeholder="è¯·éæ©å¶åº¦åç±»" style="width: 100%"> |
| | | <el-option label="人äºå¶åº¦" value="hr" /> |
| | | <el-option label="è´¢å¡å¶åº¦" value="finance" /> |
| | | <el-option label="å®å
¨å¶åº¦" value="safety" /> |
| | | <el-option label="ææ¯å¶åº¦" value="tech" /> |
| | | <el-form-item label="å¶åº¦åç±»" |
| | | prop="category"> |
| | | <el-select v-model="regulationForm.category" |
| | | placeholder="è¯·éæ©å¶åº¦åç±»" |
| | | style="width: 100%"> |
| | | <el-option label="人äºå¶åº¦" |
| | | value="hr" /> |
| | | <el-option label="è´¢å¡å¶åº¦" |
| | | value="finance" /> |
| | | <el-option label="å®å
¨å¶åº¦" |
| | | value="safety" /> |
| | | <el-option label="ææ¯å¶åº¦" |
| | | value="tech" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="å¶åº¦å
容" prop="content"> |
| | | <el-input v-model="regulationForm.content" type="textarea" :rows="10" placeholder="请è¾å
¥å¶åº¦è¯¦ç»å
容" /> |
| | | <el-form-item label="å¶åº¦å
容" |
| | | prop="content"> |
| | | <el-input v-model="regulationForm.content" |
| | | type="textarea" |
| | | :rows="10" |
| | | placeholder="请è¾å
¥å¶åº¦è¯¦ç»å
容" /> |
| | | </el-form-item> |
| | | <el-form-item label="å¶åº¦çæ¬" prop="version"> |
| | | <el-input v-model="regulationForm.version" placeholder="请è¾å
¥å¶åº¦çæ¬" /> |
| | | <el-form-item label="å¶åº¦çæ¬" |
| | | prop="version"> |
| | | <el-input v-model="regulationForm.version" |
| | | placeholder="请è¾å
¥å¶åº¦çæ¬" /> |
| | | </el-form-item> |
| | | <el-form-item label="çææ¶é´" prop="effectiveTime"> |
| | | <el-date-picker v-model="regulationForm.effectiveTime" type="datetime" format="YYYY-MM-DD HH:mm:ss" |
| | | value-format="YYYY-MM-DD HH:mm:ss" placeholder="éæ©çææ¶é´" style="width: 100%" /> |
| | | <el-form-item label="çææ¶é´" |
| | | prop="effectiveTime"> |
| | | <el-date-picker v-model="regulationForm.effectiveTime" |
| | | type="datetime" |
| | | format="YYYY-MM-DD HH:mm:ss" |
| | | value-format="YYYY-MM-DD HH:mm:ss" |
| | | placeholder="éæ©çææ¶é´" |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | <el-form-item label="éç¨èå´" prop="scope"> |
| | | <el-form-item label="éç¨èå´" |
| | | prop="scope"> |
| | | <el-checkbox-group v-model="regulationForm.scope"> |
| | | <el-checkbox label="all">å
¨ä½åå·¥</el-checkbox> |
| | | <el-checkbox label="manager">管çå±</el-checkbox> |
| | |
| | | <el-checkbox label="tech">ææ¯é¨é¨</el-checkbox> |
| | | </el-checkbox-group> |
| | | </el-form-item> |
| | | <el-form-item label="æ¯å¦éè¦ç¡®è®¤" prop="requireConfirm"> |
| | | <el-form-item label="æ¯å¦éè¦ç¡®è®¤" |
| | | prop="requireConfirm"> |
| | | <el-switch v-model="regulationForm.requireConfirm" /> |
| | | <span class="ml-10">å¼å¯ååå·¥éè¦é
读确认</span> |
| | | </el-form-item> |
| | |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button @click="showRegulationDialog = false">åæ¶</el-button> |
| | | <el-button type="primary" @click="submitRegulation">åå¸å¶åº¦</el-button> |
| | | <el-button type="primary" |
| | | @click="submitRegulation">åå¸å¶åº¦</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- ç¨å°è¯¦æ
å¯¹è¯æ¡ï¼å·²ç§»é¤ï¼ --> |
| | | |
| | | <!-- è§ç« å¶åº¦è¯¦æ
å¯¹è¯æ¡ --> |
| | | <el-dialog v-model="showRegulationDetailDialog" title="è§ç« å¶åº¦è¯¦æ
" width="800px"> |
| | | <el-dialog v-model="showRegulationDetailDialog" |
| | | title="è§ç« å¶åº¦è¯¦æ
" |
| | | width="800px"> |
| | | <div v-if="currentRegulationDetail"> |
| | | <el-descriptions :column="2" border> |
| | | <el-descriptions :column="2" |
| | | border> |
| | | <el-descriptions-item label="å¶åº¦ç¼å·">{{ currentRegulationDetail.id }}</el-descriptions-item> |
| | | <el-descriptions-item label="å¶åº¦æ é¢">{{ currentRegulationDetail.title }}</el-descriptions-item> |
| | | <el-descriptions-item label="åç±»">{{ getCategoryText(currentRegulationDetail.category) }}</el-descriptions-item> |
| | |
| | | <div class="regulation-content">{{ currentRegulationDetail.content }}</div> |
| | | </div> |
| | | <!-- 妿tableData>0 æ¾ç¤º --> |
| | | <div style="margin: 10px 0;" v-if="tableData && tableData.length > 0" > |
| | | <el-button type="success" @click="resetForm(currentRegulationDetail)">确认æ¥ç</el-button> |
| | | <div style="margin: 10px 0;" |
| | | v-if="tableData && tableData.length > 0"> |
| | | <el-button type="success" |
| | | @click="resetForm(currentRegulationDetail)">确认æ¥ç</el-button> |
| | | </div> |
| | | </div> |
| | | </el-dialog> |
| | | |
| | | <!-- çæ¬åå²å¯¹è¯æ¡ --> |
| | | <el-dialog v-model="showVersionHistoryDialog" title="çæ¬åå²" width="800px"> |
| | | <el-table :data="versionHistory" style="width: 100%;margin-bottom: 10px"> |
| | | <el-table-column prop="version" label="çæ¬å·" width="100" /> |
| | | <el-table-column prop="updateTime" label="æ´æ°æ¶é´" width="180" /> |
| | | <el-table-column prop="createUserName" label="æ´æ°äºº" width="120" /> |
| | | <el-table-column prop="changeLog" label="åæ´è¯´æ"> |
| | | <el-dialog v-model="showVersionHistoryDialog" |
| | | title="çæ¬åå²" |
| | | width="800px"> |
| | | <el-table :data="versionHistory" |
| | | style="width: 100%;margin-bottom: 10px"> |
| | | <el-table-column prop="version" |
| | | label="çæ¬å·" |
| | | width="100" /> |
| | | <el-table-column prop="updateTime" |
| | | label="æ´æ°æ¶é´" |
| | | width="180" /> |
| | | <el-table-column prop="createUserName" |
| | | label="æ´æ°äºº" |
| | | width="120" /> |
| | | <el-table-column prop="changeLog" |
| | | label="åæ´è¯´æ"> |
| | | <template #default="scope"> |
| | | <el-tag :type="scope.row.status === 'active' ? 'success' : 'info'"> |
| | | {{ scope.row.status === 'active' ? 'çæä¸' : 'å·²åºæ¢' }} |
| | |
| | | </el-table-column> |
| | | </el-table> |
| | | </el-dialog> |
| | | |
| | | <!-- é
è¯»ç¶æå¯¹è¯æ¡ --> |
| | | <el-dialog v-model="showReadStatusDialog" title="é
è¯»ç¶æ" width="800px"> |
| | | <el-table :data="readStatusList" style="width: 100%;margin-bottom: 10px"> |
| | | <el-table-column prop="employee" label="åå·¥å§å" width="120" /> |
| | | <el-table-column prop="department" label="æå±é¨é¨" width="150" /> |
| | | <el-table-column prop="createTime" label="é
读æ¶é´" width="180" /> |
| | | <el-table-column prop="confirmTime" label="确认æ¶é´" width="180" /> |
| | | <el-table-column prop="status" label="ç¶æ" width="100"> |
| | | <el-dialog v-model="showReadStatusDialog" |
| | | title="é
è¯»ç¶æ" |
| | | width="800px"> |
| | | <el-table :data="readStatusList" |
| | | style="width: 100%;margin-bottom: 10px"> |
| | | <el-table-column prop="employee" |
| | | label="åå·¥å§å" |
| | | width="120" /> |
| | | <el-table-column prop="department" |
| | | label="æå±é¨é¨" |
| | | width="150" /> |
| | | <el-table-column prop="createTime" |
| | | label="é
读æ¶é´" |
| | | width="180" /> |
| | | <el-table-column prop="confirmTime" |
| | | label="确认æ¶é´" |
| | | width="180" /> |
| | | <el-table-column prop="status" |
| | | label="ç¶æ" |
| | | width="100"> |
| | | <template #default="scope"> |
| | | <el-tag :type="scope.row.status === 'confirmed' ? 'success' : 'warning'"> |
| | | {{ scope.row.status === 'confirmed' ? '已确认' : 'æªç¡®è®¤' }} |
| | |
| | | </el-table-column> |
| | | </el-table> |
| | | </el-dialog> |
| | | |
| | | <FileListDialog |
| | | ref="fileListDialogRef" |
| | | v-model="fileDialogVisible" |
| | | :show-upload-button="true" |
| | | :show-delete-button="true" |
| | | :delete-method="handleAttachmentDelete" |
| | | :rules-regulations-management-id="currentFileRuleId" |
| | | :name-column-label="'éä»¶åç§°'" |
| | | @upload="handleAttachmentUpload" |
| | | /> |
| | | <FileListDialog ref="fileListDialogRef" |
| | | v-model="fileDialogVisible" |
| | | :show-upload-button="true" |
| | | :show-delete-button="true" |
| | | :delete-method="handleAttachmentDelete" |
| | | :rules-regulations-management-id="currentFileRuleId" |
| | | :name-column-label="'éä»¶åç§°'" |
| | | @upload="handleAttachmentUpload" /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, onMounted, getCurrentInstance } from 'vue' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | import { listRuleManagement,addRuleManagement,updateRuleManagement,delRuleManagement,getReadingStatusByRuleId,addReadingStatus,updateReadingStatus } from '@/api/collaborativeApproval/sealManagement.js' |
| | | import FileListDialog from '@/components/Dialog/FileListDialog.vue' |
| | | import { listRuleFiles, delRuleFile, addRuleFile } from '@/api/collaborativeApproval/rulesRegulationsManagementFile.js' |
| | | import { ref, reactive, onMounted, getCurrentInstance } from "vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import { |
| | | listRuleManagement, |
| | | addRuleManagement, |
| | | updateRuleManagement, |
| | | delRuleManagement, |
| | | getReadingStatusByRuleId, |
| | | addReadingStatus, |
| | | updateReadingStatus, |
| | | } from "@/api/collaborativeApproval/sealManagement.js"; |
| | | import FileListDialog from "@/components/Dialog/FileListDialog.vue"; |
| | | import { |
| | | listRuleFiles, |
| | | delRuleFile, |
| | | addRuleFile, |
| | | } from "@/api/collaborativeApproval/rulesRegulationsManagementFile.js"; |
| | | |
| | | // ååºå¼æ°æ® |
| | | const operationType = ref('add') |
| | | const tableData = ref([]) |
| | | const tableLoading = ref(false) |
| | | // å页忰 |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 10, |
| | | total: 0 |
| | | }) |
| | | // éä»¶å¼¹çª |
| | | const fileDialogVisible = ref(false) |
| | | const fileListDialogRef = ref(null) |
| | | const currentFileRuleId = ref(null) |
| | | const filePage = reactive({ |
| | | current: 1, |
| | | size: 10, |
| | | total: 0 |
| | | }) |
| | | // è§ç« å¶åº¦ç¸å
³ |
| | | const showRegulationDialog = ref(false) |
| | | const showRegulationDetailDialog = ref(false) |
| | | const showVersionHistoryDialog = ref(false) |
| | | const showReadStatusDialog = ref(false) |
| | | const currentRegulationDetail = ref(null) |
| | | const regulationFormRef = ref() |
| | | const regulationForm = reactive({ |
| | | id: '', |
| | | regulationNum: '', |
| | | title: '', |
| | | category: '', |
| | | content: '', |
| | | version: '', |
| | | status: 'active', |
| | | readCount: 0, |
| | | effectiveTime: '', |
| | | scope: [], |
| | | requireConfirm: false |
| | | }) |
| | | // ååºå¼æ°æ® |
| | | const operationType = ref("add"); |
| | | const tableData = ref([]); |
| | | const tableLoading = ref(false); |
| | | // å页忰 |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 10, |
| | | total: 0, |
| | | }); |
| | | // éä»¶å¼¹çª |
| | | const fileDialogVisible = ref(false); |
| | | const fileListDialogRef = ref(null); |
| | | const currentFileRuleId = ref(null); |
| | | const filePage = reactive({ |
| | | current: 1, |
| | | size: 10, |
| | | total: 0, |
| | | }); |
| | | // è§ç« å¶åº¦ç¸å
³ |
| | | const showRegulationDialog = ref(false); |
| | | const showRegulationDetailDialog = ref(false); |
| | | const showVersionHistoryDialog = ref(false); |
| | | const showReadStatusDialog = ref(false); |
| | | const currentRegulationDetail = ref(null); |
| | | const regulationFormRef = ref(); |
| | | const regulationForm = reactive({ |
| | | id: "", |
| | | regulationNum: "", |
| | | title: "", |
| | | category: "", |
| | | content: "", |
| | | version: "", |
| | | status: "active", |
| | | readCount: 0, |
| | | effectiveTime: "", |
| | | scope: [], |
| | | requireConfirm: false, |
| | | }); |
| | | |
| | | const readStatus = ref({ |
| | | id: '', |
| | | ruleId: '', |
| | | employee: '', |
| | | department: '', |
| | | createTime: '', |
| | | confirmTime: '', |
| | | status: 'unconfirmed' |
| | | }) |
| | | const readStatus = ref({ |
| | | id: "", |
| | | ruleId: "", |
| | | employee: "", |
| | | department: "", |
| | | createTime: "", |
| | | confirmTime: "", |
| | | status: "unconfirmed", |
| | | }); |
| | | |
| | | const regulationRules = { |
| | | title: [{ required: true, message: '请è¾å
¥å¶åº¦æ é¢', trigger: 'blur' }], |
| | | category: [{ required: true, message: 'è¯·éæ©å¶åº¦åç±»', trigger: 'change' }], |
| | | content: [{ required: true, message: '请è¾å
¥å¶åº¦å
容', trigger: 'blur' }], |
| | | effectiveTime: [{ required: true, message: 'è¯·éæ©çææ¶é´', trigger: 'change' }], |
| | | scope: [{ required: true, message: 'è¯·éæ©éç¨èå´', trigger: 'change' }] |
| | | } |
| | | const regulationRules = { |
| | | title: [{ required: true, message: "请è¾å
¥å¶åº¦æ é¢", trigger: "blur" }], |
| | | category: [{ required: true, message: "è¯·éæ©å¶åº¦åç±»", trigger: "change" }], |
| | | content: [{ required: true, message: "请è¾å
¥å¶åº¦å
容", trigger: "blur" }], |
| | | effectiveTime: [ |
| | | { required: true, message: "è¯·éæ©çææ¶é´", trigger: "change" }, |
| | | ], |
| | | scope: [{ required: true, message: "è¯·éæ©éç¨èå´", trigger: "change" }], |
| | | }; |
| | | |
| | | const regulationSearchForm = reactive({ |
| | | title: '', |
| | | category: '' |
| | | }) |
| | | const regulationSearchForm = reactive({ |
| | | title: "", |
| | | category: "", |
| | | }); |
| | | |
| | | const regulations = ref([]) |
| | | const regulations = ref([]); |
| | | |
| | | const versionHistory = ref([]) |
| | | const versionHistory = ref([]); |
| | | |
| | | const readStatusList = ref([]) |
| | | const readStatusList = ref([]); |
| | | // { employee: 'éå¿å¼º', department: 'éå®é¨', readTime: '2025-01-11 10:30:00', confirmTime: '2025-01-11 10:35:00', status: 'confirmed' }, |
| | | // { employee: 'åé
å©·', department: 'ææ¯é¨', readTime: '2025-01-11 14:20:00', confirmTime: '', status: 'unconfirmed' }, |
| | | // { employee: 'ç建å½', department: 'è´¢å¡é¨', readTime: '2025-01-12 09:15:00', confirmTime: '2025-01-12 09:20:00', status: 'confirmed' } |
| | | |
| | | // å¶åº¦åç±» |
| | | const getCategoryText = (category) => { |
| | | const categoryMap = { |
| | | hr: '人äºå¶åº¦', |
| | | finance: 'è´¢å¡å¶åº¦', |
| | | safety: 'å®å
¨å¶åº¦', |
| | | tech: 'ææ¯å¶åº¦' |
| | | } |
| | | return categoryMap[category] || 'æªç¥' |
| | | } |
| | | // æç´¢å¶åº¦ |
| | | const searchRegulations = () => { |
| | | page.current=1 |
| | | getRegulationList() |
| | | } |
| | | // éç½®å¶åº¦æç´¢ |
| | | const resetRegulationSearch = () => { |
| | | regulationSearchForm.title = '' |
| | | regulationSearchForm.category = '' |
| | | searchRegulations() |
| | | } |
| | | // æ°å¢ |
| | | const handleAdd = () => { |
| | | operationType.value = 'add' |
| | | resetRegulationForm() |
| | | showRegulationDialog.value = true |
| | | } |
| | | // å¶åº¦åç±» |
| | | const getCategoryText = category => { |
| | | const categoryMap = { |
| | | hr: "人äºå¶åº¦", |
| | | finance: "è´¢å¡å¶åº¦", |
| | | safety: "å®å
¨å¶åº¦", |
| | | tech: "ææ¯å¶åº¦", |
| | | }; |
| | | return categoryMap[category] || "æªç¥"; |
| | | }; |
| | | // æç´¢å¶åº¦ |
| | | const searchRegulations = () => { |
| | | page.current = 1; |
| | | getRegulationList(); |
| | | }; |
| | | // éç½®å¶åº¦æç´¢ |
| | | const resetRegulationSearch = () => { |
| | | regulationSearchForm.title = ""; |
| | | regulationSearchForm.category = ""; |
| | | searchRegulations(); |
| | | }; |
| | | // æ°å¢ |
| | | const handleAdd = () => { |
| | | operationType.value = "add"; |
| | | resetRegulationForm(); |
| | | showRegulationDialog.value = true; |
| | | }; |
| | | |
| | | // ç¼è¾ |
| | | const handleEdit = (row) => { |
| | | operationType.value = 'edit' |
| | | Object.assign(regulationForm, row) |
| | | showRegulationDialog.value = true |
| | | } |
| | | // åºå¼ |
| | | const repealEdit = (row) => { |
| | | operationType.value = 'edit' |
| | | Object.assign(regulationForm, row) |
| | | regulationForm.status = 'repealed' |
| | | ElMessageBox.confirm('确认åºå¼è¯¥å¶åº¦ï¼', 'æç¤º', { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | }).then(() => { |
| | | updateRuleManagement(regulationForm).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success('å¶åº¦åºå¼æå') |
| | | // showRegulationDialog.value = false |
| | | getRegulationList() |
| | | resetRegulationForm() |
| | | } |
| | | // ç¼è¾ |
| | | const handleEdit = row => { |
| | | operationType.value = "edit"; |
| | | Object.assign(regulationForm, row); |
| | | showRegulationDialog.value = true; |
| | | }; |
| | | // åºå¼ |
| | | const repealEdit = row => { |
| | | operationType.value = "edit"; |
| | | Object.assign(regulationForm, row); |
| | | regulationForm.status = "repealed"; |
| | | ElMessageBox.confirm("确认åºå¼è¯¥å¶åº¦ï¼", "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | }).catch(() => { |
| | | ElMessage({ |
| | | type: 'info', |
| | | message: '已忶åºå¼' |
| | | }) |
| | | }) |
| | | } |
| | | // åå¸å¶åº¦ |
| | | const submitRegulation = async () => { |
| | | try { |
| | | await regulationFormRef.value.validate() |
| | | if(operationType.value == 'add'){ |
| | | addRuleManagement(regulationForm).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success('å¶åº¦å叿å') |
| | | showRegulationDialog.value = false |
| | | getRegulationList() |
| | | resetRegulationForm() |
| | | } |
| | | .then(() => { |
| | | updateRuleManagement(regulationForm).then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("å¶åº¦åºå¼æå"); |
| | | // showRegulationDialog.value = false |
| | | getRegulationList(); |
| | | resetRegulationForm(); |
| | | } |
| | | }); |
| | | }) |
| | | }else{ |
| | | updateRuleManagement(regulationForm).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success('å¶åº¦ç¼è¾æå') |
| | | showRegulationDialog.value = false |
| | | resetRegulationForm() |
| | | getRegulationList() |
| | | }})} |
| | | }catch(err){ |
| | | ElMessage.error(err.msg) |
| | | } |
| | | } |
| | | //éç½®å¶åº¦è¡¨å |
| | | const resetRegulationForm = () => { |
| | | Object.assign(regulationForm, { |
| | | id: '', |
| | | regulationNum: '', |
| | | title: '', |
| | | category: '', |
| | | content: '', |
| | | version: '', |
| | | status: 'active', |
| | | readCount: 0, |
| | | effectiveTime: '', |
| | | scope: [], |
| | | requireConfirm: false |
| | | }) |
| | | } |
| | | |
| | | |
| | | // æ¥çå¶åº¦çæ¬åå² |
| | | const viewVersionHistory = (row) => { |
| | | showVersionHistoryDialog.value = true |
| | | const params = { |
| | | |
| | | category: row.category |
| | | } |
| | | listRuleManagement(page,params).then(res => { |
| | | if(res.code == 200){ |
| | | versionHistory.value = res.data.records |
| | | .catch(() => { |
| | | ElMessage({ |
| | | type: "info", |
| | | message: "已忶åºå¼", |
| | | }); |
| | | }); |
| | | }; |
| | | // åå¸å¶åº¦ |
| | | const submitRegulation = async () => { |
| | | try { |
| | | await regulationFormRef.value.validate(); |
| | | if (operationType.value == "add") { |
| | | addRuleManagement(regulationForm).then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("å¶åº¦å叿å"); |
| | | showRegulationDialog.value = false; |
| | | getRegulationList(); |
| | | resetRegulationForm(); |
| | | } |
| | | }); |
| | | } else { |
| | | updateRuleManagement(regulationForm).then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("å¶åº¦ç¼è¾æå"); |
| | | showRegulationDialog.value = false; |
| | | resetRegulationForm(); |
| | | getRegulationList(); |
| | | } |
| | | }); |
| | | } |
| | | } catch (err) { |
| | | ElMessage.error(err.msg); |
| | | } |
| | | }) |
| | | } |
| | | // æ¥çå¶åº¦è¯¦æ
|
| | | const viewRegulation = (row) => { |
| | | currentRegulationDetail.value = row |
| | | showRegulationDetailDialog.value = true |
| | | getReadingStatusByRuleId(row.id).then(res => { |
| | | if(res.code == 200){ |
| | | readStatusList.value = res.data |
| | | if(readStatusList.value.length==0 && tableData.value.length>0){ |
| | | }; |
| | | //éç½®å¶åº¦è¡¨å |
| | | const resetRegulationForm = () => { |
| | | Object.assign(regulationForm, { |
| | | id: "", |
| | | regulationNum: "", |
| | | title: "", |
| | | category: "", |
| | | content: "", |
| | | version: "", |
| | | status: "active", |
| | | readCount: 0, |
| | | effectiveTime: "", |
| | | scope: [], |
| | | requireConfirm: false, |
| | | }); |
| | | }; |
| | | |
| | | // æ¥çå¶åº¦çæ¬åå² |
| | | const viewVersionHistory = row => { |
| | | showVersionHistoryDialog.value = true; |
| | | const params = { |
| | | category: row.category, |
| | | }; |
| | | listRuleManagement(page, params).then(res => { |
| | | if (res.code == 200) { |
| | | versionHistory.value = res.data.records; |
| | | } |
| | | }); |
| | | }; |
| | | // æ¥çå¶åº¦è¯¦æ
|
| | | const viewRegulation = row => { |
| | | currentRegulationDetail.value = row; |
| | | showRegulationDetailDialog.value = true; |
| | | getReadingStatusByRuleId(row.id).then(res => { |
| | | if (res.code == 200) { |
| | | readStatusList.value = res.data; |
| | | if (readStatusList.value.length == 0 && tableData.value.length > 0) { |
| | | const params = { |
| | | ruleId: row.id, |
| | | employee: tableData.value[0].staffName, |
| | | department: tableData.value[0].postJob, |
| | | status: 'unconfirmed' |
| | | ruleId: row.id, |
| | | employee: tableData.value[0].staffName, |
| | | department: tableData.value[0].postJob, |
| | | status: "unconfirmed", |
| | | }; |
| | | addReadingStatus(params).then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("å¶åº¦é
读æå"); |
| | | } |
| | | }); |
| | | } |
| | | addReadingStatus(params).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success('å¶åº¦é
读æå') |
| | | } |
| | | }) |
| | | } |
| | | } |
| | | }) |
| | | |
| | | } |
| | | // æ¥çå¶åº¦é
è¯»ç¶æ |
| | | const viewReadStatus = (row) => { |
| | | showReadStatusDialog.value = true |
| | | //æ¥çé
è¯»ç¶æå表 |
| | | getReadingStatusByRuleId(row.id).then(res => { |
| | | if(res.code == 200){ |
| | | readStatusList.value = res.data |
| | | } |
| | | }) |
| | | } |
| | | |
| | | //确认æ¥ç |
| | | const resetForm = (row) => { |
| | | console.log("row",row) |
| | | row.readCount = row.readCount + 1 |
| | | |
| | | updateRuleManagement(row).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success('æ¥çæ°éä¿®æ¹æå') |
| | | //ä¿®æ¹é
è¯»ç¶æ |
| | | //æ ¹æ®å¶åº¦idåå½åç»å½çåå·¥å¾å°é
è¯»ç¶æ |
| | | // let item = readStatusList.value.filter(item => item.employee == tableData.value[0].staffName ) |
| | | // if(item.length>0){ |
| | | // item[0].status = 'confirmed', |
| | | // item[0].confirmTime = new Date().toISOString().replace('T', ' ').split('.')[0]; |
| | | // } |
| | | // çéå½åå工对åºè¯¥å¶åº¦çé
è¯»ç¶æè®°å½ |
| | | let statusItem = readStatusList.value.find(item => item.employee === tableData.value[0].staffName && item.ruleId === row.id); |
| | | |
| | | if (statusItem) { |
| | | // 妿æ¾å°è®°å½ï¼æ´æ°ç¶æå确认æ¶é´ |
| | | statusItem.status = 'confirmed'; |
| | | // æ ¼å¼åæ¶é´ä¸º"YYYY-MM-DD HH:mm:ss"æ ¼å¼ |
| | | const now = new Date(); |
| | | statusItem.confirmTime = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')} ${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}:${String(now.getSeconds()).padStart(2, '0')}`; |
| | | // statusItem.confirmTime = new Date().toISOString().replace('T', ' ').split('.')[0]; |
| | | |
| | | updateReadingStatus(statusItem).then(res => { |
| | | if(res.code == 200){ |
| | | ElMessage.success('å¶åº¦é
è¯»ç¶æä¿®æ¹æå') |
| | | } |
| | | }) |
| | | }); |
| | | }; |
| | | // æ¥çå¶åº¦é
è¯»ç¶æ |
| | | const viewReadStatus = row => { |
| | | showReadStatusDialog.value = true; |
| | | //æ¥çé
è¯»ç¶æå表 |
| | | getReadingStatusByRuleId(row.id).then(res => { |
| | | if (res.code == 200) { |
| | | readStatusList.value = res.data; |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | //确认æ¥ç |
| | | const resetForm = row => { |
| | | console.log("row", row); |
| | | row.readCount = row.readCount + 1; |
| | | |
| | | updateRuleManagement(row).then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("æ¥çæ°éä¿®æ¹æå"); |
| | | //ä¿®æ¹é
è¯»ç¶æ |
| | | //æ ¹æ®å¶åº¦idåå½åç»å½çåå·¥å¾å°é
è¯»ç¶æ |
| | | // let item = readStatusList.value.filter(item => item.employee == tableData.value[0].staffName ) |
| | | // if(item.length>0){ |
| | | // item[0].status = 'confirmed', |
| | | // item[0].confirmTime = new Date().toISOString().replace('T', ' ').split('.')[0]; |
| | | // } |
| | | // çéå½åå工对åºè¯¥å¶åº¦çé
è¯»ç¶æè®°å½ |
| | | let statusItem = readStatusList.value.find( |
| | | item => |
| | | item.employee === tableData.value[0].staffName && |
| | | item.ruleId === row.id |
| | | ); |
| | | |
| | | if (statusItem) { |
| | | // 妿æ¾å°è®°å½ï¼æ´æ°ç¶æå确认æ¶é´ |
| | | statusItem.status = "confirmed"; |
| | | // æ ¼å¼åæ¶é´ä¸º"YYYY-MM-DD HH:mm:ss"æ ¼å¼ |
| | | const now = new Date(); |
| | | statusItem.confirmTime = `${now.getFullYear()}-${String( |
| | | now.getMonth() + 1 |
| | | ).padStart(2, "0")}-${String(now.getDate()).padStart(2, "0")} ${String( |
| | | now.getHours() |
| | | ).padStart(2, "0")}:${String(now.getMinutes()).padStart( |
| | | 2, |
| | | "0" |
| | | )}:${String(now.getSeconds()).padStart(2, "0")}`; |
| | | // statusItem.confirmTime = new Date().toISOString().replace('T', ' ').split('.')[0]; |
| | | |
| | | updateReadingStatus(statusItem).then(res => { |
| | | if (res.code == 200) { |
| | | ElMessage.success("å¶åº¦é
è¯»ç¶æä¿®æ¹æå"); |
| | | } |
| | | }); |
| | | } |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | // 导åºè§ç« å¶åº¦ |
| | | const { proxy } = getCurrentInstance(); |
| | | const handleExport = () => { |
| | | proxy.download( |
| | | "/rulesRegulationsManagement/export", |
| | | { ...regulationSearchForm }, |
| | | "è§ç« å¶åº¦.xlsx" |
| | | ); |
| | | }; |
| | | |
| | | // éä»¶ï¼æ¥è¯¢ |
| | | const fetchRuleFiles = async rulesRegulationsManagementId => { |
| | | const params = { |
| | | current: filePage.current, |
| | | size: filePage.size, |
| | | rulesRegulationsManagementId, |
| | | }; |
| | | const res = await listRuleFiles(params); |
| | | const records = res?.data?.records || []; |
| | | filePage.total = res?.data?.total || records.length; |
| | | const mapped = records.map(item => ({ |
| | | id: item.id, |
| | | name: item.fileName || item.name, |
| | | url: item.fileUrl || item.url, |
| | | raw: item, |
| | | })); |
| | | fileListDialogRef.value?.setList(mapped); |
| | | }; |
| | | |
| | | // æå¼éä»¶å¼¹çª |
| | | const openFileDialog = async row => { |
| | | currentFileRuleId.value = row.id; |
| | | fileDialogVisible.value = true; |
| | | await fetchRuleFiles(row.id); |
| | | }; |
| | | |
| | | // å·æ°éä»¶å表 |
| | | const refreshFileList = async () => { |
| | | if (!currentFileRuleId.value) return; |
| | | await fetchRuleFiles(currentFileRuleId.value); |
| | | }; |
| | | |
| | | // ä¸ä¼ éä»¶ï¼ç±åç»ä»¶è§¦åï¼ |
| | | const handleAttachmentUpload = async filePayload => { |
| | | if (!currentFileRuleId.value) return; |
| | | const payload = { |
| | | name: filePayload?.fileName || filePayload?.name, |
| | | url: filePayload?.fileUrl || filePayload?.url, |
| | | rulesRegulationsManagementId: currentFileRuleId.value, |
| | | }; |
| | | await addRuleFile(payload); |
| | | ElMessage.success("æä»¶ä¸ä¼ æå"); |
| | | await refreshFileList(); |
| | | }; |
| | | |
| | | // å é¤éä»¶ |
| | | const handleAttachmentDelete = async row => { |
| | | if (!row?.id) return false; |
| | | try { |
| | | await ElMessageBox.confirm("确认å é¤è¯¥éä»¶ï¼", "æç¤º", { type: "warning" }); |
| | | } catch { |
| | | return false; |
| | | } |
| | | }) |
| | | } |
| | | await delRuleFile([row.id]); |
| | | ElMessage.success("å 餿å"); |
| | | await refreshFileList(); |
| | | }; |
| | | |
| | | // 导åºè§ç« å¶åº¦ |
| | | const { proxy } = getCurrentInstance() |
| | | const handleExport = () => { |
| | | proxy.download('/rulesRegulationsManagement/export', { ...regulationSearchForm }, 'è§ç« å¶åº¦.xlsx') |
| | | } |
| | | // è·åè§ç« å¶åº¦åè¡¨æ°æ® |
| | | const getRegulationList = async () => { |
| | | tableLoading.value = true; |
| | | listRuleManagement(page, regulationSearchForm) |
| | | .then(res => { |
| | | regulations.value = res.data.records; |
| | | // è¿æ»¤æå·²åºå¼çå¶åº¦ |
| | | // regulations.value = res.data.records.filter(item => item.status !== 'repealed') |
| | | page.value.total = res.data.total; |
| | | tableLoading.value = false; |
| | | }) |
| | | .catch(err => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | |
| | | // éä»¶ï¼æ¥è¯¢ |
| | | const fetchRuleFiles = async (rulesRegulationsManagementId) => { |
| | | const params = { |
| | | current: filePage.current, |
| | | size: filePage.size, |
| | | rulesRegulationsManagementId |
| | | } |
| | | const res = await listRuleFiles(params) |
| | | const records = res?.data?.records || [] |
| | | filePage.total = res?.data?.total || records.length |
| | | const mapped = records.map(item => ({ |
| | | id: item.id, |
| | | name: item.fileName || item.name, |
| | | url: item.fileUrl || item.url, |
| | | raw: item |
| | | })) |
| | | fileListDialogRef.value?.setList(mapped) |
| | | } |
| | | |
| | | // æå¼éä»¶å¼¹çª |
| | | const openFileDialog = async (row) => { |
| | | currentFileRuleId.value = row.id |
| | | fileDialogVisible.value = true |
| | | await fetchRuleFiles(row.id) |
| | | } |
| | | |
| | | // å·æ°éä»¶å表 |
| | | const refreshFileList = async () => { |
| | | if (!currentFileRuleId.value) return |
| | | await fetchRuleFiles(currentFileRuleId.value) |
| | | } |
| | | |
| | | // ä¸ä¼ éä»¶ï¼ç±åç»ä»¶è§¦åï¼ |
| | | const handleAttachmentUpload = async (filePayload) => { |
| | | if (!currentFileRuleId.value) return |
| | | const payload = { |
| | | name: filePayload?.fileName || filePayload?.name, |
| | | url: filePayload?.fileUrl || filePayload?.url, |
| | | rulesRegulationsManagementId: currentFileRuleId.value |
| | | } |
| | | await addRuleFile(payload) |
| | | ElMessage.success('æä»¶ä¸ä¼ æå') |
| | | await refreshFileList() |
| | | } |
| | | |
| | | // å é¤éä»¶ |
| | | const handleAttachmentDelete = async (row) => { |
| | | if (!row?.id) return false |
| | | try { |
| | | await ElMessageBox.confirm('确认å é¤è¯¥éä»¶ï¼', 'æç¤º', { type: 'warning' }) |
| | | } catch { |
| | | return false |
| | | } |
| | | await delRuleFile([row.id]) |
| | | ElMessage.success('å 餿å') |
| | | await refreshFileList() |
| | | } |
| | | |
| | | // è·åè§ç« å¶åº¦åè¡¨æ°æ® |
| | | const getRegulationList = async () => { |
| | | tableLoading.value = true |
| | | listRuleManagement(page,regulationSearchForm) |
| | | .then(res => { |
| | | |
| | | regulations.value = res.data.records |
| | | // è¿æ»¤æå·²åºå¼çå¶åº¦ |
| | | // regulations.value = res.data.records.filter(item => item.status !== 'repealed') |
| | | page.value.total = res.data.total; |
| | | tableLoading.value = false; |
| | | |
| | | }).catch(err => { |
| | | tableLoading.value = false; |
| | | }) |
| | | } |
| | | |
| | | onMounted(() => { |
| | | // åå§å |
| | | getRegulationList() |
| | | }) |
| | | onMounted(() => { |
| | | // åå§å |
| | | getRegulationList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .app-container { |
| | | padding: 20px; |
| | | } |
| | | .app-container { |
| | | padding: 20px; |
| | | } |
| | | |
| | | .card-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | } |
| | | .card-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | } |
| | | |
| | | .tab-content { |
| | | padding: 20px 0; |
| | | } |
| | | .tab-content { |
| | | padding: 20px 0; |
| | | } |
| | | |
| | | .mb-20 { |
| | | margin-bottom: 20px; |
| | | } |
| | | .mb-20 { |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .mt-20 { |
| | | margin-top: 20px; |
| | | } |
| | | .mt-20 { |
| | | margin-top: 20px; |
| | | } |
| | | |
| | | .ml-10 { |
| | | margin-left: 10px; |
| | | } |
| | | .ml-10 { |
| | | margin-left: 10px; |
| | | } |
| | | |
| | | .regulation-content { |
| | | background-color: #f5f5f5; |
| | | padding: 15px; |
| | | border-radius: 4px; |
| | | line-height: 1.6; |
| | | white-space: pre-wrap; |
| | | height: 200px; |
| | | } |
| | | .regulation-content { |
| | | background-color: #f5f5f5; |
| | | padding: 15px; |
| | | border-radius: 4px; |
| | | line-height: 1.6; |
| | | white-space: pre-wrap; |
| | | height: 200px; |
| | | } |
| | | |
| | | .dialog-footer { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | gap: 10px; |
| | | } |
| | | .dialog-footer { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | gap: 10px; |
| | | } |
| | | </style> |
| | |
| | | import { listSealApplication, addSealApplication, updateSealApplication,listRuleManagement,addRuleManagement,updateRuleManagement,delRuleManagement,getReadingStatusByRuleId,getReadingStatusList,addReadingStatus,updateReadingStatus } from '@/api/collaborativeApproval/sealManagement.js' |
| | | import { el } from 'element-plus/es/locales.mjs' |
| | | import { getUserProfile, userListNoPageByTenantId } from '@/api/system/user.js' |
| | | import {staffJoinDel, staffJoinListPage} from "@/api/personnelManagement/onboarding.js"; |
| | | import useUserStore from '@/store/modules/user' |
| | | import { userLoginFacotryList } from "@/api/system/user.js" |
| | | import {staffOnJobListPage} from "@/api/personnelManagement/staffOnJob.js"; |
| | | |
| | | // ååºå¼æ°æ® |
| | | const currentUser = ref(null) |
| | |
| | | currentUser.value = res.data.userName |
| | | } |
| | | }) |
| | | staffJoinListPage({staffState: 1, ...page}).then(res => { |
| | | staffOnJobListPage({staffState: 1, ...page}).then(res => { |
| | | tableLoading.value = false; |
| | | // tableData.value = res.data.records |
| | | // //çéåºåcurrentUserååç人å |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <el-dialog v-model="dialogVisible" title="éä»¶" width="40%" :before-close="handleClose"> |
| | | <el-table :data="tableData" border height="40vh"> |
| | | <el-table-column label="éä»¶åç§°" prop="name" min-width="400" show-overflow-tooltip /> |
| | | <el-table-column fixed="right" label="æä½" width="100" align="center"> |
| | | <template #default="scope"> |
| | | <el-button link type="primary" size="small" @click="downLoadFile(scope.row)">ä¸è½½</el-button> |
| | | <el-button link type="primary" size="small" @click="lookFile(scope.row)">é¢è§</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </el-dialog> |
| | | <filePreview ref="filePreviewRef" /> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref } from 'vue' |
| | | import filePreview from '@/components/filePreview/index.vue' |
| | | |
| | | const dialogVisible = ref(false) |
| | | const tableData = ref([]) |
| | | const { proxy } = getCurrentInstance(); |
| | | const filePreviewRef = ref() |
| | | const handleClose = () => { |
| | | dialogVisible.value = false |
| | | } |
| | | const open = (list) => { |
| | | dialogVisible.value = true |
| | | tableData.value = list |
| | | } |
| | | const downLoadFile = (row) => { |
| | | proxy.$download.name(row.url); |
| | | |
| | | } |
| | | const lookFile = (row) => { |
| | | filePreviewRef.value.open(row.url) |
| | | } |
| | | defineExpose({ |
| | | open |
| | | }) |
| | | </script> |
| | | |
| | | <style></style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title">éå®ååå·ï¼</span> |
| | | <el-input |
| | | v-model="searchForm.salesContractNo" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥éå®ååå·æç´¢" |
| | | @change="handleQuery" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | /> |
| | | <span class="search_title ml10">审æ¹ç¶æï¼</span> |
| | | <el-select v-model="searchForm.approveStatus" clearable @change="handleQuery" style="width: 240px"> |
| | | <el-option label="å¾
å®¡æ ¸" :value="2" /> |
| | | <el-option label="å®¡æ ¸æå" :value="3" /> |
| | | <el-option label="å®¡æ ¸å¤±è´¥" :value="4" /> |
| | | </el-select> |
| | | <el-button type="primary" @click="handleQuery" style="margin-left: 10px" |
| | | >æç´¢</el-button |
| | | > |
| | | </div> |
| | | <div> |
| | | <!-- <el-button type="primary" @click="openForm('add')">æ°å¢</el-button>--> |
| | | <el-button @click="handleOut">导åº</el-button> |
| | | <!-- <el-button type="danger" plain @click="handleDelete">å é¤</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" |
| | | :total="page.total" |
| | | ></PIMTable> |
| | | </div> |
| | | <info-form-dia ref="infoFormDia" @close="handleQuery" :approveType="approveType"></info-form-dia> |
| | | <approval-dia ref="approvalDia" @close="handleQuery"></approval-dia> |
| | | <FileList ref="fileListRef" /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import FileList from "./fileList.vue"; |
| | | import { Search } from "@element-plus/icons-vue"; |
| | | import {onMounted, ref} from "vue"; |
| | | import {ElMessageBox} from "element-plus"; |
| | | import InfoFormDia from "@/views/collaborativeApproval/approvalProcess/components/infoFormDia.vue"; |
| | | import ApprovalDia from "@/views/collaborativeApproval/approvalProcess/components/approvalDia.vue"; |
| | | import {getShipmentApprovalList, approveShipment} from "@/api/collaborativeApproval/shipmentReview.js"; |
| | | // import {approveProcessDelete, approveProcessListPage} from "@/api/collaborativeApproval/approvalProcess.js"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import { userListNoPage } from "@/api/system/user.js"; |
| | | |
| | | // å®ä¹ç»ä»¶æ¥æ¶çprops |
| | | const props = defineProps({ |
| | | approveType: { |
| | | type: [Number, String], |
| | | default: 6 |
| | | } |
| | | }); |
| | | |
| | | const userList = ref([]); |
| | | |
| | | const userStore = useUserStore(); |
| | | |
| | | |
| | | const data = reactive({ |
| | | searchForm: { |
| | | approveId: "", |
| | | approveStatus: "", |
| | | }, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "审æ¹ç¶æ", |
| | | prop: "approveStatus", |
| | | dataType: "tag", |
| | | width: 100, |
| | | formatData: (params) => { |
| | | if (params === 2) { |
| | | return "å¾
å®¡æ ¸"; |
| | | } else if (params === 3) { |
| | | return "å®¡æ ¸å®æ"; |
| | | } else if (params === 4) { |
| | | return "å®¡æ ¸é©³å"; |
| | | } else { |
| | | return 'æªç¥ç¶æ'; |
| | | } |
| | | }, |
| | | formatType: (params) => { |
| | | if (params === 0) { |
| | | return "warning"; |
| | | } else if (params === 2) { |
| | | return "info"; |
| | | } else if (params === 3) { |
| | | return "success"; |
| | | } else if (params === 4) { |
| | | return "danger"; |
| | | } else { |
| | | return 'danger'; |
| | | } |
| | | }, |
| | | }, |
| | | { |
| | | label: "éå®ååå·", |
| | | prop: "salesContractNo", |
| | | width: 170 |
| | | }, |
| | | { |
| | | label: "客æ·åç§°", |
| | | prop: "customerName", |
| | | width: 200 |
| | | }, |
| | | { |
| | | label: "产å大类", |
| | | prop: "productCategory", |
| | | width: 200 |
| | | }, |
| | | { |
| | | label: "è§æ ¼åå·", |
| | | prop: "specificationModel", |
| | | width: 220 |
| | | }, |
| | | { |
| | | label: "ç³è¯·äºº", |
| | | prop: "approveUserId", |
| | | width: 120, |
| | | align: "center", |
| | | formatData:(params)=>{ |
| | | const user = userList.value.find(item => item.userId === params) |
| | | return user ? user.nickName : '--' |
| | | } |
| | | }, |
| | | { |
| | | label: "车çå·", |
| | | prop: "shippingCarNumber", |
| | | width: 120, |
| | | }, |
| | | { |
| | | label: "ç³è¯·äºº", |
| | | prop: "approveUserId", |
| | | width: 120, |
| | | }, |
| | | { |
| | | label: "ç³è¯·æ¥æ", |
| | | prop: "executionDate", |
| | | width: 200 |
| | | }, |
| | | { |
| | | label: "å½å审æ¹äºº", |
| | | prop: "salesman", |
| | | width: 120 |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: "right", |
| | | width: 120, |
| | | operation: [ |
| | | { |
| | | name: "éè¿", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | handleApproval("éè¿", row); |
| | | }, |
| | | disabled: (row) => row.approveStatus !== 2 |
| | | }, |
| | | { |
| | | name: "驳å", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | handleApproval("驳å", row); |
| | | }, |
| | | disabled: (row) => row.approveStatus !== 2 |
| | | }, |
| | | // { |
| | | // name: "ç¼è¾", |
| | | // type: "text", |
| | | // clickFun: (row) => { |
| | | // openForm("edit", row); |
| | | // }, |
| | | // disabled: (row) => row.approveStatus == 2 || row.approveStatus == 1 || row.approveStatus == 4 |
| | | // }, |
| | | // { |
| | | // name: "å®¡æ ¸", |
| | | // type: "text", |
| | | // clickFun: (row) => { |
| | | // openApprovalDia("approval", row); |
| | | // }, |
| | | // disabled: (row) => row.approveUserCurrentId == null || row.approveStatus == 2 || row.approveStatus == 3 || row.approveStatus == 4 || row.approveUserCurrentId !== userStore.id |
| | | // }, |
| | | // { |
| | | // name: "详æ
", |
| | | // type: "text", |
| | | // clickFun: (row) => { |
| | | // openApprovalDia('view', row); |
| | | // }, |
| | | // }, |
| | | // { |
| | | // name: "éä»¶", |
| | | // type: "text", |
| | | // clickFun: (row) => { |
| | | // downLoadFile(row); |
| | | // }, |
| | | // }, |
| | | ], |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | | const selectedRows = ref([]); |
| | | const tableLoading = ref(false); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0 |
| | | }); |
| | | const infoFormDia = ref() |
| | | const approvalDia = ref() |
| | | const { proxy } = getCurrentInstance() |
| | | |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | const fileListRef = ref(null) |
| | | const downLoadFile = (row) => { |
| | | fileListRef.value.open(row.commonFileList) |
| | | |
| | | } |
| | | const pagination = (obj) => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | const getList =async () => { |
| | | let userLists = await userListNoPage(); |
| | | userList.value = userLists.data; |
| | | tableLoading.value = true; |
| | | getShipmentApprovalList({...page, ...searchForm.value,approveType:props.approveType}).then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records |
| | | page.total = res.data.total; |
| | | }).catch(err => { |
| | | tableLoading.value = false; |
| | | }) |
| | | }; |
| | | // å¯¼åº |
| | | const handleOut = () => { |
| | | const type = Number(props.approveType || 6) |
| | | const urlMap = { |
| | | 0: "/shipmentApproval/export", |
| | | } |
| | | const url = urlMap[type] || urlMap[0] |
| | | const nameMap = { |
| | | 0: "åè´§å®¡æ ¸è¡¨", |
| | | } |
| | | const fileName = nameMap[type] || nameMap[0] |
| | | proxy.download(url, {}, `${fileName}.xlsx`) |
| | | } |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = (selection) => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | |
| | | // æå¼æ°å¢ãç¼è¾å¼¹æ¡ |
| | | const openForm = (type, row) => { |
| | | nextTick(() => { |
| | | infoFormDia.value?.openDialog(type, row) |
| | | }) |
| | | }; |
| | | // æå¼æ°å¢æ£éªå¼¹æ¡ |
| | | const openApprovalDia = (type, row) => { |
| | | nextTick(() => { |
| | | approvalDia.value?.openDialog(type, row) |
| | | }) |
| | | }; |
| | | |
| | | // å®¡æ ¸éè¿/驳å |
| | | const handleApproval = (name = "å®¡æ ¸",row) => { |
| | | ElMessageBox.confirm(`éä¸çå
容å°è¢«${name}ï¼æ¯å¦ç¡®è®¤${name}ï¼`, "æç¤º", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }).then(async()=>{ |
| | | let res = await approveShipment({ |
| | | id: row.id, |
| | | approveStatus: name === "éè¿" ? 3 : 4 |
| | | }); |
| | | if(res.code === 200){ |
| | | proxy.$modal.msgSuccess(`${name}æå`); |
| | | }else{ |
| | | proxy.$modal.msgError(`${name}失败`); |
| | | } |
| | | await getList() |
| | | }).catch(err=>{ |
| | | proxy.$modal.msgError(`æªç¥é误,请è系管çå`); |
| | | }) |
| | | }; |
| | | |
| | | // å é¤ |
| | | const handleDelete = () => { |
| | | let ids = []; |
| | | if (selectedRows.value.length > 0) { |
| | | ids = selectedRows.value.map((item) => item.approveId); |
| | | } else { |
| | | proxy.$modal.msgWarning("è¯·éæ©æ°æ®"); |
| | | return; |
| | | } |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | approveProcessDelete(ids).then((res) => { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | getList(); |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped></style> |
| | |
| | | <template> |
| | | <el-form :model="form" label-width="100px" :rules="formRules" ref="formRef"> |
| | | <el-form :model="form" label-width="120px" :rules="formRules" ref="formRef"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="设å¤åç§°" prop="deviceName"> |
| | |
| | | <el-col :span="12"> |
| | | <el-form-item label="设å¤åç" prop="deviceBrand"> |
| | | <el-input v-model="form.deviceBrand" placeholder="请è¾å
¥è®¾å¤åç" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="设å¤ç±»å" prop="type"> |
| | | <el-select |
| | | v-model="form.type" |
| | | placeholder="è¯·éæ©æè¾å
¥è®¾å¤ç±»å" |
| | | clearable |
| | | filterable |
| | | allow-create |
| | | default-first-option |
| | | style="width: 100%" |
| | | @change="handleDeviceTypeChange" |
| | | > |
| | | <el-option |
| | | v-for="item in deviceTypeOptions" |
| | | :key="item" |
| | | :label="item" |
| | | :value="item" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å¯ç¨ææ§" prop="enableDepreciation"> |
| | | <el-switch v-model="form.enableDepreciation" :active-value="true" :inactive-value="false" /> |
| | | <el-form-item label="å¯ç¨ææ§" prop="isDepr"> |
| | | <el-switch v-model="form.isDepr" :active-value="1" :inactive-value="2" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12" v-if="form.isDepr === 1"> |
| | | <el-form-item label="æ¯å¹´ææ§éé¢" prop="annualDepreciationAmount"> |
| | | <el-input-number |
| | | :step="0.01" |
| | | :min="0" |
| | | style="width: 100%" |
| | | v-model="form.annualDepreciationAmount" |
| | | placeholder="请è¾å
¥æ¯å¹´ææ§éé¢" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | |
| | | }); |
| | | const formRef = ref(null); |
| | | const operationType = ref(''); |
| | | // 设å¤ç±»ååºå®é项 |
| | | const deviceTypeOptions = ref([ |
| | | 'ç产设å¤', |
| | | 'åå
¬è®¾å¤', |
| | | 'æ£æµè®¾å¤', |
| | | 'è¿è¾è®¾å¤', |
| | | 'å
¶ä»è®¾å¤' |
| | | ]); |
| | | const formRules = { |
| | | deviceName: [{ required: true, trigger: "blur", message: "请è¾å
¥" }], |
| | | deviceModel: [{ required: true, trigger: "blur", message: "请è¾å
¥" }], |
| | | type: [{ required: true, trigger: "change", message: "è¯·éæ©æè¾å
¥è®¾å¤ç±»å" }], |
| | | supplierName: [{ required: true, trigger: "blur", message: "请è¾å
¥" }], |
| | | unit: [{ required: true, trigger: "blur", message: "请è¾å
¥" }], |
| | | number: [{ required: true, trigger: "blur", message: "请è¾å
¥" }], |
| | | taxIncludingPriceUnit: [{ required: true, trigger: "blur", message: "请è¾å
¥" }], |
| | | taxRate: [{ required: true, trigger: "change", message: "请è¾å
¥" }], |
| | | planRuntimeTime: [{ required: true, trigger: "change", message: "è¯·éæ©" }], |
| | | annualDepreciationAmount: [ |
| | | { |
| | | validator: (rule, value, callback) => { |
| | | if (form.isDepr === 1 && (value === undefined || value === null || value === '')) { |
| | | callback(new Error('å¯ç¨ææ§æ¶ï¼è¯·è¾å
¥æ¯å¹´ææ§éé¢')); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }, |
| | | trigger: "blur" |
| | | } |
| | | ], |
| | | } |
| | | |
| | | const { form, resetForm } = useFormData({ |
| | | deviceName: undefined, // 设å¤åç§° |
| | | deviceModel: undefined, // è§æ ¼åå· |
| | | deviceBrand: undefined, // 设å¤åç |
| | | type: undefined, // 设å¤ç±»å |
| | | supplierName: undefined, // ä¾åºå |
| | | storageLocation: undefined, // åæ¾ä½ç½® |
| | | enableDepreciation: false, // æ¯å¦å¯ç¨ææ§ |
| | | isDepr: 2, // æ¯å¦å¯ç¨ææ§ 1-æ¯ 2-å¦ |
| | | annualDepreciationAmount: undefined, // æ¯å¹´ææ§éé¢ |
| | | unit: undefined, // åä½ |
| | | number: 1, // æ°é |
| | | taxIncludingPriceUnit: undefined, // å«ç¨åä»· |
| | |
| | | form.deviceName = data.deviceName; |
| | | form.deviceModel = data.deviceModel; |
| | | form.deviceBrand = data.deviceBrand; |
| | | form.type = data.type; |
| | | form.supplierName = data.supplierName; |
| | | form.storageLocation = data.storageLocation; |
| | | form.enableDepreciation = data.enableDepreciation; |
| | | form.isDepr = data.isDepr; |
| | | form.annualDepreciationAmount = data.annualDepreciationAmount; |
| | | form.unit = data.unit; |
| | | form.number = 1; |
| | | form.taxIncludingPriceUnit = data.taxIncludingPriceUnit; |
| | |
| | | } |
| | | }; |
| | | |
| | | const handleDeviceTypeChange = (value) => { |
| | | // 妿è¾å
¥çæ°å¼ä¸å¨åºå®é项ä¸ï¼åæ·»å å°é项å表 |
| | | if (value && !deviceTypeOptions.value.includes(value)) { |
| | | deviceTypeOptions.value.push(value); |
| | | } |
| | | }; |
| | | |
| | | const mathNum = () => { |
| | | if (!form.taxIncludingPriceUnit) { |
| | | ElMessage.error("请è¾å
¥åä»·"); |
| | |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥è®¾å¤åç§°" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | @change="getTableData" |
| | | /> |
| | | </el-form-item> |
| | |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥è§æ ¼åå·" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | @change="getTableData" |
| | | /> |
| | | </el-form-item> |
| | |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥ä¾åºå" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | @change="getTableData" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="åä½"> |
| | | <el-input |
| | | v-model="filters.unit" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥åä½" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | @change="getTableData" |
| | | /> |
| | | </el-form-item> |
| | |
| | | deviceName: undefined, |
| | | deviceModel: undefined, |
| | | supplierName: undefined, |
| | | unit: undefined, |
| | | entryDateStart: undefined, |
| | | entryDateEnd: undefined, |
| | | }, |
| | | [ |
| | | { |
| | | label: "设å¤åç§°", |
| | | align: "center", |
| | | prop: "deviceName", |
| | | }, |
| | | { |
| | | label: "è§æ ¼åå·", |
| | | align: "center", |
| | | prop: "deviceModel", |
| | | }, |
| | | { |
| | | label: "设å¤åç", |
| | | align: "center", |
| | | prop: "deviceBrand", |
| | | }, |
| | | { |
| | | label: "设å¤ç±»å", |
| | | prop: "type", |
| | | }, |
| | | { |
| | | label: "ä¾åºå", |
| | | align: "center", |
| | | prop: "supplierName", |
| | | }, |
| | | { |
| | | label: "åä½", |
| | | align: "center", |
| | | prop: "unit", |
| | | }, |
| | | { |
| | | label: "åæ¾ä½ç½®", |
| | | align: "center", |
| | | prop: "storageLocation", |
| | | }, |
| | | { |
| | | label: "æ°é", |
| | | align: "center", |
| | | prop: "number", |
| | | }, |
| | | { |
| | | label: "å«ç¨åä»·", |
| | | align: "center", |
| | | prop: "taxIncludingPriceUnit", |
| | | }, |
| | | { |
| | | label: "å«ç¨æ»ä»·", |
| | | align: "center", |
| | | prop: "taxIncludingPriceTotal", |
| | | }, |
| | | { |
| | | label: "ç¨ç", |
| | | align: "center", |
| | | prop: "taxRate", |
| | | }, |
| | | { |
| | | label: "ä¸å«ç¨æ»ä»·", |
| | | align: "center", |
| | | prop: "unTaxIncludingPriceTotal", |
| | | }, |
| | | { |
| | | label: "å¯ç¨ææ§", |
| | | align: "center", |
| | | prop: "enableDepreciation", |
| | | formatData: (v) => (v ? "æ¯" : "å¦"), |
| | | }, |
| | | { |
| | | label: "å½å
¥äºº", |
| | | align: "center", |
| | | prop: "createUser", |
| | | }, |
| | | { |
| | | label: "å½å
¥æ¥æ", |
| | | align: "center", |
| | | prop: "createTime", |
| | | formatData: (v) => { |
| | | if (!v) return ''; |
| | | // 妿å
嫿¶åç§ï¼åªåæ¥æé¨å |
| | | if (v.includes(' ')) { |
| | | return v.split(' ')[0]; |
| | | } |
| | | return v; |
| | | }, |
| | | }, |
| | | { |
| | | dataType: "action", |
| | |
| | | operation: [ |
| | | { |
| | | name: "ç¼è¾", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | edit(row.id) |
| | | }, |
| | | }, |
| | | { |
| | | name: "çæäºç»´ç ", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | showQRCode(row) |
| | | }, |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | |
| | | </template> |
| | | |
| | | <script setup> |
| | | |
| | | </script> |
| | |
| | | ref="formRef" |
| | | > |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="计éå¨å
·ç¼å·ï¼" prop="code"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="åºåç¼å·ï¼" prop="code"> |
| | | <el-input |
| | | v-model="form.code" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="计éå¨å
·åç§°ï¼" prop="name"> |
| | | <el-input |
| | | v-model="form.name" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="è§æ ¼åå·ï¼" prop="model"> |
| | | <el-form-item label="å®è£
ä½ç½®ï¼" prop="installationLocation"> |
| | | <el-input |
| | | v-model="form.model" |
| | | v-model="form.installationLocation" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="é¢è®¡ä¸æ¬¡æ£å®æ¥æï¼" prop="nextDate"> |
| | | <el-date-picker |
| | | style="width: 100%" |
| | | v-model="form.nextDate" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="date" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | /> |
| | | <el-form-item label="æ£å®åä½ï¼" prop="unit"> |
| | | <el-input |
| | | v-model="form.unit" |
| | | placeholder="请è¾å
¥æ£å®åä½" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="è¯ä¹¦ç¼å·ï¼" prop="model"> |
| | | <el-input |
| | | v-model="form.model" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ææ°é´å®æ¥æï¼" prop="mostDate"> |
| | | <el-date-picker |
| | | style="width: 100%" |
| | | v-model="form.mostDate" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="date" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æææ¥æ(天)ï¼" prop="valid"> |
| | | <el-input |
| | | v-model="form.valid" |
| | | placeholder="请è¾å
¥æææå¤©æ°" |
| | | clearable |
| | | > |
| | | <template #append>æ¥</template> |
| | | </el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ£å®å¨æï¼" prop="cycle"> |
| | | <el-input |
| | | v-model="form.cycle" |
| | | placeholder="请è¾å
¥æ£å®å¨æ" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å½å
¥äººï¼" prop="userId"> |
| | |
| | | style="width: 100%" |
| | | v-model="form.recordDate" |
| | | value-format="YYYY-MM-DD" |
| | | disabled |
| | | format="YYYY-MM-DD" |
| | | type="date" |
| | | placeholder="è¯·éæ©" |
| | |
| | | import {userListNoPageByTenantId} from "@/api/system/user.js"; |
| | | import {afterSalesServiceAdd, afterSalesServiceUpdate} from "@/api/customerService/index.js"; |
| | | import {getToken} from "@/utils/auth.js"; |
| | | import {measuringInstrumentAdd, measuringInstrumentUpdate} from "@/api/equipmentManagement/measurementEquipment.js"; |
| | | import {addMeasuringInstrumentLedger, updateMeasuringInstrumentLedger} from "@/api/equipmentManagement/measurementEquipment.js"; |
| | | import { getCurrentDate } from "@/utils/index.js"; |
| | | const { proxy } = getCurrentInstance() |
| | | const emit = defineEmits(['close']) |
| | |
| | | const data = reactive({ |
| | | form: { |
| | | code: "", |
| | | name: "", |
| | | installationLocation: "", |
| | | mostDate:"", |
| | | model: "", |
| | | cycle:"", |
| | | validDate: "", |
| | | nextDate: "", |
| | | userId: "", |
| | |
| | | }, |
| | | rules: { |
| | | code: [{required: true, message: "请è¾å
¥", trigger: "blur"}], |
| | | name: [{required: true, message: "请è¾å
¥", trigger: "blur"}], |
| | | model: [{required: true, message: "请è¾å
¥", trigger: "blur"}], |
| | | validDate: [{required: true, message: "请è¾å
¥", trigger: "blur"}], |
| | | nextDate: [{required: true, message: "è¯·éæ©", trigger: "change"}], |
| | | userId: [{required: true, message: "è¯·éæ©", trigger: "change"}], |
| | | recordDate: [{required: true, message: "è¯·éæ©", trigger: "change"}], |
| | | installationLocation: [{required: true, message: "请è¾å
¥", trigger: "blur"}], |
| | | mostDate: [{required: true, message: "è¯·éæ©", trigger: "change"}], |
| | | cycle: [{required: true, message: "è¯·éæ©", trigger: "blur"}], |
| | | valid: [{required: true, message: "请è¾å
¥", trigger: "blur"}], |
| | | unit: [{required: true, message: "请è¾å
¥", trigger: "blur"}], |
| | | } |
| | | }) |
| | | const { form, rules } = toRefs(data); |
| | |
| | | proxy.$refs["formRef"].validate(valid => { |
| | | if (valid) { |
| | | if (operationType.value === "add") { |
| | | measuringInstrumentAdd(form.value).then(response => { |
| | | addMeasuringInstrumentLedger(form.value).then(response => { |
| | | proxy.$modal.msgSuccess("æ°å¢æå") |
| | | form.value.tempFileIds = [] |
| | | closeDia() |
| | | }) |
| | | } else { |
| | | measuringInstrumentUpdate(form.value).then(response => { |
| | | updateMeasuringInstrumentLedger(form.value).then(response => { |
| | | proxy.$modal.msgSuccess("ä¿®æ¹æå") |
| | | form.value.tempFileIds = [] |
| | | closeDia() |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div> |
| | | <el-dialog |
| | | v-model="dialogFormVisible" |
| | | title="æ£å®æ ¡åè®°å½" |
| | | width="50%" |
| | | @close="closeDia" |
| | | > |
| | | <PIMTable |
| | | rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :tableLoading="tableLoading" |
| | | @selection-change="handleSelectionChange" |
| | | height="500" |
| | | :isPagination="false" |
| | | > |
| | | </PIMTable> |
| | | <pagination |
| | | style="margin: 10px 0" |
| | | v-show="total > 0" |
| | | @pagination="paginationSearch" |
| | | :total="total" |
| | | :page="page.current" |
| | | :limit="page.size" |
| | | /> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button @click="closeDia">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | <filePreview ref="filePreviewRef" /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {ref} from "vue"; |
| | | import filePreview from '@/components/filePreview/index.vue' |
| | | import {ledgerRecordListPage} from "@/api/equipmentManagement/calibration.js"; |
| | | import Pagination from "@/components/PIMTable/Pagination.vue"; |
| | | const emit = defineEmits(['close']) |
| | | |
| | | const dialogFormVisible = ref(false); |
| | | const currentId = ref('') |
| | | const selectedRows = ref([]); |
| | | const filePreviewRef = ref() |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "æ£å®æ¥æ", |
| | | prop: "recordDate", |
| | | width: 130, |
| | | }, |
| | | { |
| | | label: "计éå¨å
·ç¼å·", |
| | | prop: "code", |
| | | width: 150, |
| | | }, |
| | | { |
| | | label: "计éå¨å
·åç§°", |
| | | prop: "name", |
| | | width: 200, |
| | | }, |
| | | { |
| | | label: "è§æ ¼åå·", |
| | | prop: "model", |
| | | width:200 |
| | | }, |
| | | { |
| | | label: "æææ", |
| | | prop: "valid", |
| | | width: 100, |
| | | }, |
| | | { |
| | | label: "å½å
¥äºº", |
| | | prop: "userName", |
| | | }, |
| | | { |
| | | label: "å½å
¥æ¥æ", |
| | | prop: "entryDate", |
| | | width: 130, |
| | | }, |
| | | ]); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | }); |
| | | const total = ref(0); |
| | | const tableData = ref([]); |
| | | const tableLoading = ref(false); |
| | | |
| | | // æå¼å¼¹æ¡ |
| | | const openDialog = (row,type) => { |
| | | dialogFormVisible.value = true; |
| | | currentId.value = row.id; |
| | | getList() |
| | | } |
| | | const paginationSearch = (obj) => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | const getList = () => { |
| | | let query = { |
| | | measuringInstrumentLedgerId:currentId.value, |
| | | current : page.current, |
| | | size : page.size |
| | | } |
| | | ledgerRecordListPage(query).then(res => { |
| | | tableData.value = res?.data?.records || []; |
| | | total.value = res?.data?.total; |
| | | }) |
| | | } |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = (selection) => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | |
| | | // å
³éå¼¹æ¡ |
| | | const closeDia = () => { |
| | | dialogFormVisible.value = false; |
| | | emit('close') |
| | | }; |
| | | |
| | | defineExpose({ |
| | | openDialog, |
| | | }); |
| | | </script> |
| | |
| | | @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> |
| | | </template> |
| | | |
| | |
| | | import useUserStore from "@/store/modules/user.js"; |
| | | import CalibrationDia from "@/views/equipmentManagement/measurementEquipment/components/calibrationDia.vue"; |
| | | import { |
| | | measuringInstrumentDelete, |
| | | measuringInstrumentListPage |
| | | 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 tableColumn = ref([ |
| | | { |
| | | label: "ç¶æ", |
| | | prop: "status", |
| | | dataType: "tag", |
| | | formatData: (params) => { |
| | | if (params == 1) { |
| | | return "ææ"; |
| | | } else if (params == 2) { |
| | | return "龿"; |
| | | } else { |
| | | return null; |
| | | } |
| | | }, |
| | | formatType: (params) => { |
| | | if (params == 1) { |
| | | return "success"; |
| | | } else if (params == 2) { |
| | | return "danger"; |
| | | } else { |
| | | return null; |
| | | } |
| | | }, |
| | | label: "åºåç¼å·", |
| | | prop: "code", |
| | | minWidth:150, |
| | | align:"center" |
| | | }, |
| | | { |
| | | label: "æè¿ä¸æ¬¡æ£å®æ¥æ", |
| | | label: "é¨é¨", |
| | | prop: "deptName", |
| | | width: 130, |
| | | align:"center" |
| | | }, |
| | | { |
| | | label: "å®è£
ä½ç½®", |
| | | prop: "installationLocation", |
| | | width: 150, |
| | | align:"center" |
| | | }, |
| | | { |
| | | label: "æ£å®åä½", |
| | | prop: "unit", |
| | | width: 200, |
| | | align:"center" |
| | | }, |
| | | { |
| | | label: "è¯ä¹¦ç¼å·", |
| | | prop: "model", |
| | | width:200, |
| | | align:"center" |
| | | }, |
| | | { |
| | | label: "ææ°é´å®æ¥æ", |
| | | prop: "mostDate", |
| | | width: 130, |
| | | }, |
| | | { |
| | | label: "计éå¨å
·ç¼å·", |
| | | prop: "code", |
| | | width: 150, |
| | | }, |
| | | { |
| | | label: "计éå¨å
·åç§°", |
| | | prop: "name", |
| | | width: 200, |
| | | }, |
| | | { |
| | | label: "è§æ ¼åå·", |
| | | prop: "model", |
| | | width:200 |
| | | }, |
| | | { |
| | | label: "æææ", |
| | | prop: "valid", |
| | | width: 130, |
| | | }, |
| | | { |
| | | label: "é¢è®¡ä¸æ¬¡æ£å®æ¥æ", |
| | | prop: "nextDate", |
| | | width: 130, |
| | | align:"center" |
| | | }, |
| | | { |
| | | label: "å½å
¥äºº", |
| | | prop: "userName", |
| | | width: 130, |
| | | align:"center" |
| | | }, |
| | | { |
| | | label: "å½å
¥æ¥æ", |
| | | prop: "recordDate", |
| | | width: 130, |
| | | 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; |
| | | } |
| | | } |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | |
| | | width: '130', |
| | | fixed: 'right', |
| | | operation: [ |
| | | { |
| | | name: "éä»¶", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | openFilesFormDia(row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "æ£å®æ ¡å", |
| | | name: "æ¥ç", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | openCalibrationDia("verifying", row); |
| | | }, |
| | | }, |
| | | // { |
| | | // name: "éä»¶", |
| | | // type: "text", |
| | | // clickFun: (row) => { |
| | | // openFilesFormDia(row); |
| | | // }, |
| | | // }, |
| | | ], |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | | const tableLoading = ref(false); |
| | | const rowClickData = ref([]) |
| | | const filesDia = ref() |
| | | const page = reactive({ |
| | | current: 1, |
| | |
| | | |
| | | // æå¼éä»¶å¼¹æ¡ |
| | | const openFilesFormDia = (row) => { |
| | | console.log(row) |
| | | nextTick(() => { |
| | | filesDia.value?.openDialog( row,'计éå¨å
·å°è´¦') |
| | | }) |
| | | filesDia.value?.openDialog(row,'计éå¨å
·å°è´¦') |
| | | }; |
| | | |
| | | const dbRowClick = (row)=>{ |
| | | rowClickData.value?.openDialog(row) |
| | | } |
| | | |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = (selection) => { |
| | | selectedRows.value = selection; |
| | |
| | | <template> |
| | | <el-dialog v-model="visible" :title="modalOptions.title" direction="ltr" draggable> |
| | | <MaintainForm ref="maintainFormRef" /> |
| | | <template #footer> |
| | | <el-button type="primary" @click="sendForm" :loading="loading"> |
| | | {{ modalOptions.confirmText }} |
| | | </el-button> |
| | | <el-button @click="closeModal">{{ modalOptions.cancelText }}</el-button> |
| | | </template> |
| | | </el-dialog> |
| | | <FormDialog |
| | | v-model="visible" |
| | | :title="'设å¤ç»´ä¿®'" |
| | | width="500px" |
| | | @confirm="sendForm" |
| | | @cancel="handleCancel" |
| | | @close="handleClose" |
| | | > |
| | | <el-form :model="form" label-width="80px"> |
| | | <el-form-item label="维修人"> |
| | | <el-input v-model="form.maintenanceName" placeholder="请è¾å
¥ç»´ä¿®äºº" /> |
| | | </el-form-item> |
| | | <el-form-item label="ç»´ä¿®ç»æ"> |
| | | <el-input v-model="form.maintenanceResult" placeholder="请è¾å
¥ç»´ä¿®ç»æ" /> |
| | | </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-select> |
| | | </el-form-item> |
| | | <el-form-item label="ç»´ä¿®æ¥æ"> |
| | | <el-date-picker |
| | | v-model="form.maintenanceTime" |
| | | 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> |
| | | </FormDialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { useModal } from "@/hooks/useModal"; |
| | | import MaintainForm from "../Form/MaintainForm.vue"; |
| | | import FormDialog from "@/components/Dialog/FormDialog.vue"; |
| | | import { addMaintain } from "@/api/equipmentManagement/repair"; |
| | | import useFormData from "@/hooks/useFormData"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import dayjs from "dayjs"; |
| | | import { ElMessage } from "element-plus"; |
| | | |
| | | defineOptions({ |
| | | name: "ç»´ä¿®æ¨¡ææ¡", |
| | | }); |
| | | |
| | | const maintainFormRef = ref(); |
| | | const emits = defineEmits(["ok"]); |
| | | |
| | | const { |
| | | id, |
| | | visible, |
| | | loading, |
| | | openModal, |
| | | modalOptions, |
| | | handleConfirm, |
| | | closeModal, |
| | | } = useModal({ title: "设å¤ç»´ä¿®" }); |
| | | // ä¿åæ¥ä¿®è®°å½çid |
| | | const repairId = ref(); |
| | | const visible = ref(false); |
| | | const loading = ref(false); |
| | | |
| | | const userStore = useUserStore(); |
| | | const { form, resetForm } = useFormData({ |
| | | maintenanceName: undefined, // ç»´ä¿®åç§° |
| | | maintenanceResult: undefined, // ç»´ä¿®ç»æ |
| | | maintenanceTime: undefined, // ç»´ä¿®æ¥æ |
| | | status: 0, |
| | | }); |
| | | |
| | | const setForm = (data) => { |
| | | form.maintenanceName = data.maintenanceName ?? userStore.nickName; |
| | | form.maintenanceResult = data.maintenanceResult; |
| | | form.maintenanceTime = |
| | | data.maintenanceTime |
| | | ? dayjs(data.maintenanceTime).format("YYYY-MM-DD HH:mm:ss") |
| | | : dayjs().format("YYYY-MM-DD HH:mm:ss"); |
| | | form.status = 1; // é»è®¤ç¶æä¸ºå®ç» |
| | | }; |
| | | |
| | | const sendForm = async () => { |
| | | loading.value = true; |
| | | const form = await maintainFormRef.value.getForm(); |
| | | const { code } = await addMaintain({ id: id.value, ...form }); |
| | | if (code == 200) { |
| | | emits("ok"); |
| | | maintainFormRef.value.resetForm(); |
| | | closeModal(); |
| | | try { |
| | | const { code } = await addMaintain({ id: repairId.value, ...form }); |
| | | if (code == 200) { |
| | | ElMessage.success("ç»´ä¿®æå"); |
| | | emits("ok"); |
| | | resetForm(); |
| | | visible.value = false; |
| | | } |
| | | } finally { |
| | | loading.value = false; |
| | | } |
| | | loading.value = false; |
| | | }; |
| | | |
| | | const handleCancel = () => { |
| | | resetForm(); |
| | | visible.value = false; |
| | | }; |
| | | |
| | | const handleClose = () => { |
| | | resetForm(); |
| | | visible.value = false; |
| | | }; |
| | | |
| | | const open = async (id, row) => { |
| | | openModal(id); |
| | | repairId.value = id; // ä¿åæ¥ä¿®è®°å½çid |
| | | visible.value = true; |
| | | await nextTick(); |
| | | maintainFormRef.value.setForm(row); |
| | | setForm(row); |
| | | }; |
| | | |
| | | defineExpose({ |
| | |
| | | <template> |
| | | <el-dialog v-model="visible" :title="modalOptions.title" @close="close" draggable> |
| | | <RepairForm ref="repairFormRef" :id="id" /> |
| | | <template #footer> |
| | | <el-button type="primary" @click="sendForm" :loading="loading"> |
| | | {{ modalOptions.confirmText }} |
| | | </el-button> |
| | | <el-button @click="closeModal">{{ modalOptions.cancelText }}</el-button> |
| | | </template> |
| | | </el-dialog> |
| | | <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-select v-model="form.deviceLedgerId" @change="setDeviceModel" filterable> |
| | | <el-option |
| | | v-for="(item, index) in deviceOptions" |
| | | :key="index" |
| | | :label="item.deviceName" |
| | | :value="item.id" |
| | | ></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="è§æ ¼åå·"> |
| | | <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%" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ¥ä¿®äºº"> |
| | | <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"> |
| | | <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-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="24"> |
| | | <el-form-item label="æ
éç°è±¡"> |
| | | <el-input |
| | | v-model="form.remark" |
| | | :rows="2" |
| | | type="textarea" |
| | | placeholder="请è¾å
¥æ
éç°è±¡" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | </FormDialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { useModal } from "@/hooks/useModal"; |
| | | import RepairForm from "../Form/RepairForm.vue"; |
| | | import FormDialog from "@/components/Dialog/FormDialog.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"; |
| | | |
| | | defineOptions({ |
| | | name: "è®¾å¤æ¥ä¿®å¼¹çª", |
| | |
| | | |
| | | const emits = defineEmits(["ok"]); |
| | | |
| | | const repairFormRef = ref(); |
| | | const { |
| | | id, |
| | | visible, |
| | | loading, |
| | | openModal, |
| | | modalOptions, |
| | | handleConfirm, |
| | | closeModal, |
| | | } = useModal({ title: "è®¾å¤æ¥ä¿®" }); |
| | | const id = ref(); |
| | | const visible = ref(false); |
| | | const loading = ref(false); |
| | | |
| | | const userStore = useUserStore(); |
| | | const deviceOptions = ref([]); |
| | | |
| | | const loadDeviceName = async () => { |
| | | const { data } = await getDeviceLedger(); |
| | | deviceOptions.value = data; |
| | | }; |
| | | |
| | | const { form, resetForm } = useFormData({ |
| | | deviceLedgerId: undefined, // 设å¤Id |
| | | deviceName: undefined, // 设å¤åç§° |
| | | deviceModel: undefined, // è§æ ¼åå· |
| | | repairTime: dayjs().format("YYYY-MM-DD"), // æ¥ä¿®æ¥æï¼é»è®¤å½å¤© |
| | | repairName: userStore.nickName, // æ¥ä¿®äºº |
| | | remark: undefined, // æ
éç°è±¡ |
| | | status: 0, // æ¥ä¿®ç¶æ |
| | | }); |
| | | |
| | | const setDeviceModel = (deviceId) => { |
| | | const option = deviceOptions.value.find((item) => item.id === deviceId); |
| | | form.deviceModel = option.deviceModel; |
| | | }; |
| | | |
| | | 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; |
| | | }; |
| | | |
| | | const sendForm = async () => { |
| | | loading.value = true; |
| | | const form = await repairFormRef.value.getForm(); |
| | | const { code } = id.value |
| | | ? await editRepair({ id: unref(id), ...form }) |
| | | : await addRepair(form); |
| | | if (code == 200) { |
| | | ElMessage.success(`${id ? "ç¼è¾" : "æ°å¢"}æ¥ä¿®æå`); |
| | | closeModal(); |
| | | emits("ok"); |
| | | 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; |
| | | } |
| | | loading.value = false; |
| | | }; |
| | | |
| | | const handleCancel = () => { |
| | | resetForm(); |
| | | visible.value = false; |
| | | }; |
| | | |
| | | const handleClose = () => { |
| | | resetForm(); |
| | | visible.value = false; |
| | | }; |
| | | |
| | | const openAdd = async () => { |
| | | openModal(); |
| | | id.value = undefined; |
| | | visible.value = true; |
| | | await nextTick(); |
| | | await repairFormRef.value.loadDeviceName(); |
| | | await loadDeviceName(); |
| | | }; |
| | | |
| | | const openEdit = async (id) => { |
| | | const { data } = await getRepairById(id); |
| | | openModal(id); |
| | | const openEdit = async (editId) => { |
| | | const { data } = await getRepairById(editId); |
| | | id.value = editId; |
| | | visible.value = true; |
| | | await nextTick(); |
| | | await repairFormRef.value.loadDeviceName(); |
| | | await repairFormRef.value.setForm(data); |
| | | }; |
| | | |
| | | const close = () => { |
| | | repairFormRef.value.resetForm(); |
| | | closeModal(); |
| | | await loadDeviceName(); |
| | | setForm(data); |
| | | }; |
| | | |
| | | defineExpose({ |
| | |
| | | openEdit, |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped></style> |
| | |
| | | å¯¼åº |
| | | </el-button> |
| | | <el-button |
| | | type="danger" |
| | | icon="Delete" |
| | | :disabled="multipleList.length <= 0" |
| | | @click="delRepairByIds(multipleList.map((item) => item.id))" |
| | | type="danger" |
| | | icon="Delete" |
| | | :disabled="multipleList.length <= 0 || hasFinishedStatus" |
| | | @click="delRepairByIds(multipleList.map((item) => item.id))" |
| | | > |
| | | æ¹éå é¤ |
| | | </el-button> |
| | |
| | | </template> |
| | | <template #operation="{ row }"> |
| | | <el-button |
| | | type="primary" |
| | | text |
| | | @click="addMaintain(row)" |
| | | > |
| | | æ°å¢ç»´ä¿® |
| | | </el-button> |
| | | <el-button |
| | | type="primary" |
| | | text |
| | | icon="editPen" |
| | | @click="editRepair(row.id)" |
| | | type="primary" |
| | | link |
| | | :disabled="row.status === 1" |
| | | @click="editRepair(row.id)" |
| | | > |
| | | ç¼è¾ |
| | | </el-button> |
| | | <el-button |
| | | type="danger" |
| | | text |
| | | icon="delete" |
| | | @click="delRepairByIds(row.id)" |
| | | 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> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { usePaginationApi } from "@/hooks/usePaginationApi"; |
| | | import { onMounted, getCurrentInstance, computed } from "vue"; |
| | | import {usePaginationApi} from "@/hooks/usePaginationApi"; |
| | | import {getRepairPage, delRepair} from "@/api/equipmentManagement/repair"; |
| | | import {onMounted, getCurrentInstance} from "vue"; |
| | | import RepairModal from "./Modal/RepairModal.vue"; |
| | | import {ElMessageBox, ElMessage} from "element-plus"; |
| | | import dayjs from "dayjs"; |
| | |
| | | multipleList.value = selectionList; |
| | | }; |
| | | |
| | | // æ£æ¥éä¸çè®°å½ä¸æ¯å¦æå®ç»ç¶æç |
| | | const hasFinishedStatus = computed(() => { |
| | | return multipleList.value.some(item => item.status === 1) |
| | | }) |
| | | |
| | | // æ°å¢æ¥ä¿® |
| | | const addRepair = () => { |
| | | repairModalRef.value.openAdd(); |
| | |
| | | |
| | | // åè¡å é¤ |
| | | 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: "åæ¶", |
| | |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="price" label="ä»·æ ¼" width="140"></el-table-column> |
| | | <el-table-column prop="quantity" label="æ°é" width="140"></el-table-column> |
| | | <el-table-column prop="description" label="æè¿°" width="150"></el-table-column> |
| | | <el-table-column label="æä½" width="150" fixed="right" align="center"> |
| | | <template #default="{ row }"> |
| | |
| | | </el-form-item> |
| | | <el-form-item label="å¤ä»¶ç¼å·" prop="sparePartsNo"> |
| | | <el-input v-model="form.sparePartsNo"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="æ°é" prop="quantity"> |
| | | <el-input type="number" v-model="form.quantity"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="ç¶æ" prop="status"> |
| | | <el-select v-model="form.status" placeholder="è¯·éæ©ç¶æ"> |
| | |
| | | sparePartsNo: [ |
| | | { required: true, message: '请è¾å
¥å¤ä»¶ç¼å·', trigger: 'blur' } |
| | | ], |
| | | quantity:[ |
| | | { required: true, message: '请è¾å
¥æ°é', trigger: 'blur' } |
| | | ], |
| | | status: [ |
| | | { required: true, message: 'è¯·éæ©ç¶æ', trigger: 'change' } |
| | | ], |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <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-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-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-select> |
| | | </el-form-item> |
| | | <el-form-item label="ä¿å
ȍȾ"> |
| | | <el-input |
| | | v-model="form.maintenanceResult" |
| | | placeholder="请è¾å
¥ä¿å
ȍȾ" |
| | | type="text" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | </FormDialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | | 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"; |
| | | |
| | | defineOptions({ |
| | | name: "ä¿å
»æ¨¡ææ¡", |
| | | }); |
| | | |
| | | const emits = defineEmits(["ok"]); |
| | | |
| | | // ä¿å计åä¿å
»è®°å½ç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, // ä¿å
»ç¶æ |
| | | }); |
| | | |
| | | 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; // é»è®¤ç¶æä¸ºå®ç» |
| | | }; |
| | | |
| | | /** |
| | | * @desc ä¿åä¿å
» |
| | | */ |
| | | const sendForm = async () => { |
| | | loading.value = true; |
| | | try { |
| | | const { code } = await addMaintenance({ id: planId.value, ...form }); |
| | | if (code == 200) { |
| | | ElMessage.success("ä¿å
»æå"); |
| | | emits("ok"); |
| | | resetForm(); |
| | | visible.value = false; |
| | | } |
| | | } finally { |
| | | loading.value = false; |
| | | } |
| | | }; |
| | | |
| | | const handleCancel = () => { |
| | | resetForm(); |
| | | visible.value = false; |
| | | }; |
| | | |
| | | const handleClose = () => { |
| | | resetForm(); |
| | | visible.value = false; |
| | | }; |
| | | |
| | | const open = async (id, row) => { |
| | | planId.value = id; // ä¿å计åä¿å
»è®°å½çid |
| | | visible.value = true; |
| | | await nextTick(); |
| | | setForm(row); |
| | | }; |
| | | |
| | | defineExpose({ |
| | | open, |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped></style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <FormDialog |
| | | v-model="visible" |
| | | :title="id ? 'ç¼è¾è®¾å¤ä¿å
»è®¡å' : 'æ°å¢è®¾å¤ä¿å
»è®¡å'" |
| | | width="500px" |
| | | @confirm="sendForm" |
| | | @cancel="handleCancel" |
| | | @close="handleClose" |
| | | > |
| | | <el-form :model="form" label-width="100px"> |
| | | <el-form-item label="设å¤åç§°"> |
| | | <el-select |
| | | v-model="form.deviceLedgerId" |
| | | @change="setDeviceModel" |
| | | placeholder="è¯·éæ©è®¾å¤" |
| | | filterable |
| | | default-first-option |
| | | :reserve-keyword="false" |
| | | > |
| | | <el-option |
| | | v-for="(item, index) in deviceOptions" |
| | | :key="index" |
| | | :label="item.deviceName" |
| | | :value="item.id" |
| | | ></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="è§æ ¼åå·"> |
| | | <el-input |
| | | v-model="form.deviceModel" |
| | | placeholder="请è¾å
¥è§æ ¼åå·" |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="å½å
¥äºº"> |
| | | <el-select |
| | | v-model="form.createUser" |
| | | placeholder="è¯·éæ©" |
| | | filterable |
| | | default-first-option |
| | | :reserve-keyword="false" |
| | | clearable |
| | | > |
| | | <el-option |
| | | v-for="item in userList" |
| | | :key="item.userId" |
| | | :label="item.nickName" |
| | | :value="item.userId" |
| | | /> |
| | | </el-select> |
| | | </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-select> |
| | | </el-form-item> |
| | | <el-form-item label="计åä¿å
»æ¥æ"> |
| | | <el-date-picker |
| | | style="width: 100%" |
| | | v-model="form.maintenancePlanTime" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD HH:mm:ss" |
| | | type="date" |
| | | placeholder="è¯·éæ©è®¡åä¿å
»æ¥ææ¥æ" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-form> |
| | | </FormDialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import FormDialog from "@/components/Dialog/FormDialog.vue"; |
| | | 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"; |
| | | |
| | | defineOptions({ |
| | | name: "设å¤ä¿å
»æ°å¢è®¡å", |
| | | }); |
| | | |
| | | const emits = defineEmits(["ok"]); |
| | | |
| | | const id = ref(); |
| | | const visible = ref(false); |
| | | const loading = ref(false); |
| | | |
| | | const deviceOptions = ref([]); |
| | | const loadDeviceName = async () => { |
| | | const { data } = await getDeviceLedger(); |
| | | deviceOptions.value = data; |
| | | }; |
| | | |
| | | const { form, resetForm } = useFormData({ |
| | | deviceLedgerId: undefined, // 设å¤Id |
| | | 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; |
| | | }; |
| | | |
| | | /** |
| | | * @desc 设置表åå
容 |
| | | * @param data 设å¤ä¿¡æ¯ |
| | | */ |
| | | const setForm = (data) => { |
| | | form.deviceLedgerId = data.deviceLedgerId; |
| | | form.deviceName = data.deviceName; |
| | | form.deviceModel = data.deviceModel; |
| | | form.createUser = Number(data.createUser); |
| | | form.status = data.status; |
| | | form.maintenancePlanTime = dayjs(data.maintenancePlanTime).format( |
| | | "YYYY-MM-DD HH:mm:ss" |
| | | ); |
| | | }; |
| | | |
| | | // ç¨æ·å表 |
| | | const userList = ref([]); |
| | | |
| | | onMounted(() => { |
| | | loadDeviceName(); |
| | | userListNoPage().then((res) => { |
| | | userList.value = res.data; |
| | | }); |
| | | }); |
| | | |
| | | const openEdit = async (editId) => { |
| | | const { data } = await getUpkeepById(editId); |
| | | id.value = editId; |
| | | visible.value = true; |
| | | await nextTick(); |
| | | setForm(data); |
| | | }; |
| | | |
| | | const sendForm = async () => { |
| | | loading.value = true; |
| | | try { |
| | | const { code } = id.value |
| | | ? await editUpkeep({ id: unref(id), ...form }) |
| | | : await addUpkeep(form); |
| | | 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 openModal = () => { |
| | | id.value = undefined; |
| | | visible.value = true; |
| | | }; |
| | | |
| | | defineExpose({ |
| | | openModal, |
| | | openEdit, |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped></style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <FormDialog |
| | | v-model="dialogVisitable" |
| | | :title="operationType === 'add' ? 'æ°å¢ä¿å
»ä»»å¡' : 'ç¼è¾ä¿å
»ä»»å¡'" |
| | | width="800px" |
| | | :operation-type="operationType" |
| | | @confirm="submitForm" |
| | | @cancel="cancel" |
| | | @close="cancel" |
| | | > |
| | | <el-form ref="formRef" :model="form" :rules="rules" label-width="120px"> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="设å¤åç§°" prop="taskId"> |
| | | <el-select v-model="form.taskId" @change="setDeviceModel" filterable> |
| | | <el-option |
| | | v-for="(item, index) in deviceOptions" |
| | | :key="index" |
| | | :label="item.deviceName" |
| | | :value="item.id" |
| | | ></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="è§æ ¼åå·"> |
| | | <el-input |
| | | v-model="form.deviceModel" |
| | | placeholder="请è¾å
¥è§æ ¼åå·" |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å½å
¥äºº" prop="inspector"> |
| | | <el-select |
| | | v-model="form.inspector" |
| | | filterable |
| | | default-first-option |
| | | :reserve-keyword="false" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | > |
| | | <el-option |
| | | v-for="item in userList" |
| | | :label="item.nickName" |
| | | :value="item.userId" |
| | | :key="item.userId" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç»è®°æ¶é´" prop="registrationDate"> |
| | | <el-date-picker |
| | | v-model="form.registrationDate" |
| | | type="date" |
| | | placeholder="éæ©ç»è®°æ¥æ" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" |
| | | style="width: 100%" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ä»»å¡é¢ç" prop="frequencyType"> |
| | | <el-select v-model="form.frequencyType" placeholder="è¯·éæ©" clearable> |
| | | <el-option label="æ¯æ¥" value="DAILY"/> |
| | | <el-option label="æ¯å¨" value="WEEKLY"/> |
| | | <el-option label="æ¯æ" value="MONTHLY"/> |
| | | <el-option label="å£åº¦" value="QUARTERLY"/> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12" v-if="form.frequencyType === 'DAILY' && form.frequencyType"> |
| | | <el-form-item label="æ¥æ" prop="frequencyDetail"> |
| | | <el-time-picker v-model="form.frequencyDetail" placeholder="éæ©æ¶é´" format="HH:mm" |
| | | value-format="HH:mm" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12" v-if="form.frequencyType === 'WEEKLY' && form.frequencyType"> |
| | | <el-form-item label="æ¥æ" prop="frequencyDetail"> |
| | | <el-select v-model="form.week" placeholder="è¯·éæ©" clearable style="width: 50%"> |
| | | <el-option label="å¨ä¸" value="MON"/> |
| | | <el-option label="å¨äº" value="TUE"/> |
| | | <el-option label="å¨ä¸" value="WED"/> |
| | | <el-option label="å¨å" value="THU"/> |
| | | <el-option label="å¨äº" value="FRI"/> |
| | | <el-option label="å¨å
" value="SAT"/> |
| | | <el-option label="卿¥" value="SUN"/> |
| | | </el-select> |
| | | <el-time-picker v-model="form.time" placeholder="éæ©æ¶é´" format="HH:mm" |
| | | value-format="HH:mm" style="width: 50%"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12" v-if="form.frequencyType === 'MONTHLY' && form.frequencyType"> |
| | | <el-form-item label="æ¥æ" prop="frequencyDetail"> |
| | | <el-date-picker |
| | | v-model="form.frequencyDetail" |
| | | type="datetime" |
| | | clearable |
| | | placeholder="éæ©å¼å§æ¥æ" |
| | | format="DD,HH:mm" |
| | | value-format="DD,HH:mm" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12" v-if="form.frequencyType === 'QUARTERLY' && form.frequencyType"> |
| | | <el-form-item label="æ¥æ" prop="frequencyDetail"> |
| | | <el-date-picker |
| | | v-model="form.frequencyDetail" |
| | | type="datetime" |
| | | clearable |
| | | placeholder="éæ©å¼å§æ¥æ" |
| | | format="MM,DD,HH:mm" |
| | | value-format="MM,DD,HH:mm" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="夿³¨" prop="remarks"> |
| | | <el-input v-model="form.remarks" placeholder="请è¾å
¥å¤æ³¨" type="textarea" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | </FormDialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import FormDialog from "@/components/Dialog/FormDialog.vue"; |
| | | import { reactive, ref, getCurrentInstance, toRefs } from "vue"; |
| | | import {userListNoPageByTenantId} from "@/api/system/user.js"; |
| | | import { getDeviceLedger } from "@/api/equipmentManagement/ledger"; |
| | | import { deviceMaintenanceTaskAdd, deviceMaintenanceTaskEdit } from "@/api/equipmentManagement/upkeep"; |
| | | import { getCurrentDate } from "@/utils/index.js"; |
| | | import useUserStore from "@/store/modules/user.js"; |
| | | |
| | | const { proxy } = getCurrentInstance() |
| | | const emit = defineEmits() |
| | | const dialogVisitable = ref(false); |
| | | const operationType = ref('add'); |
| | | const deviceOptions = ref([]); |
| | | const userStore = useUserStore(); |
| | | const data = reactive({ |
| | | form: { |
| | | taskId: undefined, |
| | | taskName: undefined, |
| | | // å½å
¥äººï¼åéä¸ä¸ªç¨æ· id |
| | | inspector: undefined, |
| | | remarks: '', |
| | | frequencyType: '', |
| | | frequencyDetail: '', |
| | | week: '', |
| | | time: '', |
| | | deviceModel: undefined, // è§æ ¼åå· |
| | | registrationDate: '' |
| | | }, |
| | | rules: { |
| | | taskId: [{ required: true, message: "è¯·éæ©è®¾å¤", trigger: "change" },], |
| | | inspector: [{ required: true, message: "è¯·éæ©å½å
¥äºº", trigger: "blur" },], |
| | | registrationDate: [{ required: true, message: "è¯·éæ©ç»è®°æ¶é´", trigger: "change" }] |
| | | } |
| | | }) |
| | | const { form, rules } = toRefs(data) |
| | | const userList = ref([]) |
| | | |
| | | const loadDeviceName = async () => { |
| | | const { data } = await getDeviceLedger(); |
| | | deviceOptions.value = data; |
| | | }; |
| | | |
| | | // éæ©è®¾å¤æ¶ï¼å填设å¤åç§°(taskName)åè§æ ¼åå·(deviceModel) |
| | | const setDeviceModel = (id) => { |
| | | const option = deviceOptions.value.find((item) => item.id === id); |
| | | if (option) { |
| | | form.value.taskId = option.id; |
| | | form.value.taskName = option.deviceName; |
| | | form.value.deviceModel = option.deviceModel; |
| | | } |
| | | } |
| | | |
| | | // æå¼å¼¹æ¡ |
| | | const openDialog = async (type, row) => { |
| | | dialogVisitable.value = true |
| | | operationType.value = type |
| | | |
| | | // é置表å |
| | | resetForm(); |
| | | |
| | | // å è½½ç¨æ·å表 |
| | | userListNoPageByTenantId().then((res) => { |
| | | userList.value = res.data; |
| | | }); |
| | | |
| | | // å 载设å¤å表 |
| | | await loadDeviceName(); |
| | | |
| | | if (type === 'edit' && row) { |
| | | form.value = { ...row } |
| | | // ç¼è¾æ¶ç¨æ¥å£è¿åç registrantId åæ¾å½å
¥äºº |
| | | if (row.registrantId) { |
| | | form.value.inspector = row.registrantId |
| | | } |
| | | |
| | | // 妿æè®¾å¤IDï¼èªå¨è®¾ç½®è®¾å¤ä¿¡æ¯ |
| | | if (form.value.taskId) { |
| | | setDeviceModel(form.value.taskId); |
| | | } |
| | | } else if (type === 'add') { |
| | | // æ°å¢æ¶è®¾ç½®ç»è®°æ¥æä¸ºå½å¤© |
| | | form.value.registrationDate = getCurrentDate(); |
| | | // æ°å¢æ¶è®¾ç½®å½å
¥äººä¸ºå½åç»å½è´¦æ· |
| | | form.value.inspector = userStore.id; |
| | | } |
| | | } |
| | | |
| | | // å
³éå¯¹è¯æ¡ |
| | | const cancel = () => { |
| | | resetForm() |
| | | dialogVisitable.value = false |
| | | emit('closeDia') |
| | | } |
| | | |
| | | // é置表å彿° |
| | | const resetForm = () => { |
| | | if (proxy.$refs.formRef) { |
| | | proxy.$refs.formRef.resetFields() |
| | | } |
| | | // éç½®è¡¨åæ°æ®ç¡®ä¿è®¾å¤ä¿¡æ¯æ£ç¡®éç½® |
| | | form.value = { |
| | | taskId: undefined, |
| | | taskName: undefined, |
| | | inspector: undefined, |
| | | inspector: undefined, |
| | | remarks: '', |
| | | frequencyType: '', |
| | | frequencyDetail: '', |
| | | week: '', |
| | | time: '', |
| | | deviceModel: undefined, |
| | | registrationDate: '' |
| | | } |
| | | } |
| | | |
| | | // æäº¤è¡¨å |
| | | const submitForm = () => { |
| | | proxy.$refs["formRef"].validate(async valid => { |
| | | if (valid) { |
| | | try { |
| | | const payload = { ...form.value } |
| | | // ä¸åååç«¯ä¼ ä¿å
»äººå段ï¼ä»
ä½¿ç¨æ¥å£è¦æ±ç registrant / registrantId |
| | | // æ ¹æ®éæ©ç"å½å
¥äºº"设置 registrant / registrantId |
| | | if (payload.inspector) { |
| | | const selectedUser = userList.value.find( |
| | | (u) => String(u.userId) === String(payload.inspector) |
| | | ) |
| | | if (selectedUser) { |
| | | payload.registrantId = selectedUser.userId |
| | | payload.registrant = selectedUser.nickName |
| | | } |
| | | } |
| | | delete payload.inspector |
| | | delete payload.inspectorIds |
| | | |
| | | if (payload.frequencyType === 'WEEKLY') { |
| | | let frequencyDetail = '' |
| | | frequencyDetail = payload.week + ',' + payload.time |
| | | payload.frequencyDetail = frequencyDetail |
| | | } |
| | | |
| | | // å½å
¥æ¥æï¼ç´æ¥ä½¿ç¨è¡¨åéç registrationDate åæ®µ |
| | | // ä¸äºé»è®¤ç¶æå段 |
| | | if (payload.status === undefined || payload.status === null || payload.status === '') { |
| | | payload.status = '0' // é»è®¤ç¶æï¼å¯æå®é
æä¸¾è°æ´ |
| | | } |
| | | payload.active = true |
| | | payload.deleted = 0 |
| | | |
| | | if (operationType.value === 'edit') { |
| | | await deviceMaintenanceTaskEdit(payload) |
| | | } else { |
| | | await deviceMaintenanceTaskAdd(payload) |
| | | } |
| | | cancel() |
| | | proxy.$modal.msgSuccess('æäº¤æå') |
| | | } catch (error) { |
| | | proxy.$modal.msgError('æäº¤å¤±è´¥ï¼è¯·éè¯') |
| | | } |
| | | } |
| | | }) |
| | | } |
| | | defineExpose({ openDialog }) |
| | | </script> |
| | | |
| | | <style scoped> |
| | | |
| | | </style> |
| | |
| | | <template #operation="{ row }"> |
| | | <el-button |
| | | type="primary" |
| | | text |
| | | icon="editPen" |
| | | link |
| | | @click="editScheduledTask(row)" |
| | | > |
| | | ç¼è¾ |
| | | </el-button> |
| | | <el-button |
| | | type="danger" |
| | | text |
| | | icon="delete" |
| | | link |
| | | @click="delScheduledTaskByIds(row.id)" |
| | | > |
| | | å é¤ |
| | |
| | | <el-button |
| | | type="danger" |
| | | icon="Delete" |
| | | :disabled="multipleList.length <= 0" |
| | | :disabled="multipleList.length <= 0 || hasFinishedStatus" |
| | | @click="delRepairByIds(multipleList.map((item) => item.id))" |
| | | > |
| | | æ¹éå é¤ |
| | |
| | | </el-button> |
| | | <el-button |
| | | type="primary" |
| | | text |
| | | icon="editPen" |
| | | 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" |
| | | text |
| | | icon="delete" |
| | | link |
| | | :disabled="row.status === 1" |
| | | @click="delRepairByIds(row.id)" |
| | | > |
| | | å é¤ |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, onMounted, reactive, getCurrentInstance, nextTick } from 'vue' |
| | | 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 './Modal/PlanModal.vue' |
| | | import MaintenanceModal from './Modal/MaintenanceModal.vue' |
| | | import FormDia from './Modal/formDia.vue' |
| | | import PlanModal from './Form/PlanModal.vue' |
| | | import MaintenanceModal from './Form/MaintenanceModal.vue' |
| | | import FormDia from './Form/formDia.vue' |
| | | import { |
| | | getUpkeepPage, |
| | | delUpkeep, |
| | |
| | | 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 |
| | |
| | | } |
| | | |
| | | const delRepairByIds = async (ids) => { |
| | | // æ£æ¥æ¯å¦æå®ç»ç¶æçè®°å½ |
| | | const hasFinished = multipleList.value.some(item => item.status === 1) |
| | | if (hasFinished) { |
| | | ElMessage.warning('ä¸è½å é¤ç¶æä¸ºå®ç»çè®°å½') |
| | | return |
| | | } |
| | | |
| | | try { |
| | | await ElMessageBox.confirm('确认å é¤ä¿å
»æ°æ®, æ¤æä½ä¸å¯é?', 'è¦å', { |
| | | confirmButtonText: 'ç¡®å®', |
| | |
| | | <div style="padding: 20px;"> |
| | | <!-- 页颿 é¢åç鿡件 --> |
| | | <div class="w-full md:w-auto flex items-center gap-3" style="margin-bottom: 20px;"> |
| | | <el-button |
| | | type="primary" |
| | | icon="Refresh" |
| | | @click="resetFilters" |
| | | size="default" |
| | | > |
| | | æ¥è¯¢ |
| | | </el-button> |
| | | <el-form :inline="true"> |
| | | <el-form-item label="年份"> |
| | | <el-date-picker |
| | | v-model="selectedYear" |
| | | type="year" |
| | | placeholder="è¯·éæ©å¹´ä»½" |
| | | format="YYYY" |
| | | value-format="YYYY" |
| | | clearable |
| | | @change="fetchData()" |
| | | style="width: 200px" |
| | | :disabled-date="(date) => date.getFullYear() > new Date().getFullYear()" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button |
| | | type="primary" |
| | | icon="Refresh" |
| | | @click="resetFilters" |
| | | size="default" |
| | | > |
| | | éç½® |
| | | </el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | |
| | | <main class="container mx-auto px-4 pb-10"> |
| | |
| | | <el-card class="bg3"> |
| | | <p>èµäº§åå¼</p> |
| | | <h3> |
| | | ¥{{ assetInfo.totalOriginalValue }} |
| | | ¥{{ formatCurrency(assetInfo.totalOriginalValue) }} |
| | | </h3> |
| | | </el-card> |
| | | |
| | |
| | | <el-card class="bg4"> |
| | | <p>ç´¯è®¡ææ§</p> |
| | | <h3> |
| | | ¥{{ assetInfo.totalDepreciation }} |
| | | ¥{{ formatCurrency(assetInfo.totalDepreciation) }} |
| | | </h3> |
| | | </el-card> |
| | | |
| | |
| | | <el-card class="bg5"> |
| | | <p>åå¼</p> |
| | | <h3> |
| | | ¥{{ assetInfo.totalNetValue }} |
| | | ¥{{ formatCurrency(assetInfo.totalNetValue) }} |
| | | </h3> |
| | | </el-card> |
| | | <!-- è´åº --> |
| | | <el-card class="bg2"> |
| | | <p>è´åº</p> |
| | | <h3> |
| | | ¥{{ formatCurrency(assetInfo.debt) }} |
| | | </h3> |
| | | </el-card> |
| | | <!-- åºåèµäº§ --> |
| | | <el-card class="bg3"> |
| | | <p>åºåèµäº§</p> |
| | | <h3> |
| | | ¥{{ formatCurrency(assetInfo.inventoryValue) }} |
| | | </h3> |
| | | </el-card> |
| | | </div> |
| | |
| | | style="height: 260px; width: 35%;"> |
| | | <div class="chart-num"> |
| | | <span style="font-size: 22px;">设å¤ç±»å</span> |
| | | <span style="font-size: 36px; font-weight: 500; font-family: 'MyCustomFont', sans-serif;">{{ assetInfo.totalEquipment }}</span> |
| | | <span style="font-size: 36px; font-weight: 500; font-family: 'MyCustomFont', sans-serif;">{{ deviceTypeTotalCount }}</span> |
| | | </div> |
| | | </Echarts> |
| | | <Echarts |
| | |
| | | style="width: 100%" |
| | | :header-cell-style="{ background: '#f5f7fa', color: '#606266' }" |
| | | > |
| | | <el-table-column prop="id" label="èµäº§ç¼å·" width="120" /> |
| | | <el-table-column prop="deviceName" label="设å¤åç§°" width="250" /> |
| | | <el-table-column prop="deviceModel" label="åå·è§æ ¼" min-width="150" /> |
| | | <el-table-column prop="supplierName" label="ä¾åºå" min-width="120" /> |
| | |
| | | <el-table-column prop="number" label="æ°é" width="120" /> |
| | | <el-table-column prop="originalValue" label="åå¼(å
)" width="120"> |
| | | <template #default="{ row }"> |
| | | ¥{{ formatCurrency(row.taxIncludingPriceTotal) }} |
| | | {{ formatCurrency(row.taxIncludingPriceTotal) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="depreciation" label="ç´¯è®¡ææ§(å
)" width="140"> |
| | | <template #default="{ row }"> |
| | | ¥{{ formatCurrency(row.taxIncludingPriceTotal-row.unTaxIncludingPriceTotal) }} |
| | | {{ formatCurrency(row.deprAmount) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="netValue" label="åå¼(å
)" width="120"> |
| | | <template #default="{ row }"> |
| | | ¥{{ formatCurrency(row.unTaxIncludingPriceTotal) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="status" label="ç¶æ" width="100"> |
| | | <template #default="{ row }"> |
| | | <el-tag |
| | | :type="getStatusTagType(row.status)" |
| | | size="small" |
| | | > |
| | | {{ row.status }} |
| | | </el-tag> |
| | | {{ formatCurrency(row.netValue) }} |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | |
| | | import { ref, computed, onMounted, reactive } from 'vue'; |
| | | import 'element-plus/dist/index.css'; |
| | | import Echarts from "@/components/Echarts/echarts.vue"; |
| | | import { getLedgerPage, getAssetInfo } from "@/api/equipmentManagement/ledger"; |
| | | import { getLedgerPage } from "@/api/equipmentManagement/ledger"; |
| | | import { getAccountingTotal, getDeviceTypeDistribution, getCalculateDepreciation } from "@/api/financialManagement/accounting"; |
| | | import dayjs from "dayjs"; |
| | | |
| | | // ç鿡件 |
| | | const dateRange = ref(null); |
| | | const equipmentType = ref(''); |
| | | const selectedYear = ref(dayjs().format('YYYY')); // é»è®¤å½å年份 |
| | | |
| | | |
| | | // åºå®èµäº§ä¿¡æ¯ |
| | | const assetInfo = ref({ |
| | | totalEquipment: 0, |
| | | totalOriginalValue: 0, |
| | | totalDepreciation: 0, |
| | | totalNetValue: 0 |
| | | totalEquipment: 0, // deviceTotal |
| | | totalOriginalValue: 0, // deviceAmount |
| | | totalDepreciation: 0, // deprAmount |
| | | totalNetValue: 0, // netValue |
| | | debt: 0, // è´åº |
| | | inventoryValue: 0 // åºåèµäº§ |
| | | }); |
| | | |
| | | // 设å¤ç±»åæ»æ°ï¼ç¨äºå¾è¡¨æ¾ç¤ºï¼ |
| | | const deviceTypeTotalCount = ref(0); |
| | | |
| | | // 设å¤å表 |
| | | const equipmentList = ref([]); |
| | |
| | | const fetchData = async () => { |
| | | try { |
| | | // è·ååºå®èµäº§æ±æ»ä¿¡æ¯ |
| | | const assetInfoRes = await getAssetInfo({ |
| | | const assetInfoRes = await getAccountingTotal({ |
| | | startDate: dateRange.value ? dateRange.value[0] : null, |
| | | endDate: dateRange.value ? dateRange.value[1] : null, |
| | | equipmentType: equipmentType.value |
| | | equipmentType: equipmentType.value, |
| | | year: selectedYear.value |
| | | }); |
| | | |
| | | if (assetInfoRes.code === 200) { |
| | | assetInfo.value = assetInfoRes.data; |
| | | // æ å°åç«¯åæ®µå°åç«¯åæ®µ |
| | | const data = assetInfoRes.data; |
| | | assetInfo.value = { |
| | | totalEquipment: data.deviceTotal || 0, // è®¾å¤æ»æ° |
| | | totalOriginalValue: data.deviceAmount || 0, // èµäº§åå¼ |
| | | totalDepreciation: data.deprAmount || 0, // ç´¯è®¡ææ§ |
| | | totalNetValue: data.netValue || 0, // åå¼ |
| | | debt: data.debt || 0, // è´åº |
| | | inventoryValue: data.inventoryValue || 0 // åºåèµäº§ |
| | | }; |
| | | } |
| | | |
| | | // è·å设å¤å表 |
| | | const equipmentListRes = await getLedgerPage({ |
| | | current: pagination.value.currentPage, |
| | | size: pagination.value.pageSize, |
| | | // è·å设å¤ç±»åå叿°æ®ï¼é¥¼å¾åæçº¿å¾ï¼ |
| | | const distributionRes = await getDeviceTypeDistribution({ |
| | | startDate: dateRange.value ? dateRange.value[0] : null, |
| | | endDate: dateRange.value ? dateRange.value[1] : null, |
| | | equipmentType: equipmentType.value |
| | | equipmentType: equipmentType.value, |
| | | year: selectedYear.value |
| | | }); |
| | | |
| | | if (equipmentListRes.code === 200) { |
| | | equipmentList.value = equipmentListRes.data.records; |
| | | pagination.value.total = equipmentListRes.data.total; |
| | | |
| | | // æ ¹æ® equipmentList æ deviceName è¿è¡åç±»ç»è®¡ |
| | | const deviceNameMap = {}; |
| | | equipmentList.value.forEach(item => { |
| | | const deviceName = item.deviceName; |
| | | if (!deviceNameMap[deviceName]) { |
| | | deviceNameMap[deviceName] = { |
| | | name: deviceName, |
| | | count: 0, |
| | | totalValue: 0 |
| | | }; |
| | | } |
| | | deviceNameMap[deviceName].count += item.number || 1; // å设 number ä¸ºè®¾å¤æ°é |
| | | deviceNameMap[deviceName].totalValue += item.taxIncludingPriceTotal || 0; // ç´¯å å«ç¨æ»ä»· |
| | | }); |
| | | |
| | | // 转æ¢ä¸º typeDistributionData æ ¼å¼ |
| | | typeDistributionData.value = Object.values(deviceNameMap).map(item => ({ |
| | | name: item.name, |
| | | value: item.count, |
| | | count: item.count, |
| | | amount: `Â¥${formatCurrency(item.totalValue)}` |
| | | })); |
| | | if (distributionRes.code === 200) { |
| | | const data = distributionRes.data; |
| | | |
| | | // æ´æ°è®¾å¤ç±»åæ»æ° |
| | | deviceTypeTotalCount.value = data.totalCount || 0; |
| | | |
| | | // 转æ¢é¥¼å¾æ°æ®æ ¼å¼ |
| | | if (data.details && data.details.length > 0) { |
| | | typeDistributionData.value = data.details.map(item => ({ |
| | | name: item.type || '', |
| | | value: Number(item.count || 0), |
| | | count: Number(item.count || 0), |
| | | amount: `Â¥${formatCurrency(item.amount || 0)}` |
| | | })); |
| | | } else if (data.categories && data.categories.length > 0) { |
| | | // å¦ææ²¡æ detailsï¼ä½¿ç¨ categoriesãcountData å amountData æå»º |
| | | typeDistributionData.value = data.categories.map((category, index) => ({ |
| | | name: category, |
| | | value: Number(data.countData[index] || 0), |
| | | count: Number(data.countData[index] || 0), |
| | | amount: `Â¥${formatCurrency(data.amountData[index] || 0)}` |
| | | })); |
| | | } else { |
| | | typeDistributionData.value = []; |
| | | } |
| | | |
| | | // æ´æ°xè½´æ°æ® |
| | | xAxis.value[0].data = typeDistributionData.value.map(item => item.name); |
| | | xAxis.value[0].data = data.categories || typeDistributionData.value.map(item => item.name); |
| | | |
| | | // æå»ºæçº¿å¾æ°æ® |
| | | typeDistributionLineSeries.value = [ |
| | | { |
| | | name: 'è®¾å¤æ°é', |
| | | type: 'line', |
| | | data: typeDistributionData.value.map(item => item.count) |
| | | data: data.countData || typeDistributionData.value.map(item => item.count) |
| | | } |
| | | ]; |
| | | } |
| | | |
| | | // è·å设å¤åè¡¨ï¼ææ§è®¡ç®æ°æ®ï¼ |
| | | const equipmentListRes = await getCalculateDepreciation({ |
| | | current: pagination.value.currentPage, |
| | | size: pagination.value.pageSize, |
| | | startDate: dateRange.value ? dateRange.value[0] : null, |
| | | endDate: dateRange.value ? dateRange.value[1] : null, |
| | | equipmentType: equipmentType.value, |
| | | year: selectedYear.value |
| | | }); |
| | | |
| | | if (equipmentListRes.code === 200) { |
| | | // 妿è¿åçæ¯åé¡µæ°æ® |
| | | if (equipmentListRes.data.records) { |
| | | equipmentList.value = equipmentListRes.data.records; |
| | | pagination.value.total = equipmentListRes.data.total; |
| | | } else if (Array.isArray(equipmentListRes.data)) { |
| | | // 妿è¿åçæ¯æ°ç» |
| | | equipmentList.value = equipmentListRes.data; |
| | | pagination.value.total = equipmentListRes.data.length; |
| | | } else { |
| | | equipmentList.value = []; |
| | | pagination.value.total = 0; |
| | | } |
| | | } |
| | | } catch (error) { |
| | | console.error('è·ååºå®èµäº§æ°æ®å¤±è´¥ï¼', error); |
| | |
| | | const resetFilters = () => { |
| | | dateRange.value = null; |
| | | equipmentType.value = ''; |
| | | selectedYear.value = dayjs().format('YYYY'); // é置为å½å年份 |
| | | fetchData(); |
| | | }; |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | /* 大å±å¹åä»¥ä¸ (lg:grid-cols-5) */ |
| | | /* 大å±å¹åä»¥ä¸ (lg:grid-cols-6) */ |
| | | @media (min-width: 1024px) { |
| | | .grid-container { |
| | | grid-template-columns: repeat(5, minmax(0, 1fr)); |
| | | grid-template-columns: repeat(6, minmax(0, 1fr)); |
| | | } |
| | | } |
| | | |
| | |
| | | <template> |
| | | <el-dialog :title="modalOptions.title" v-model="visible" @close="close" width="30%"> |
| | | <Form ref="formRef"></Form> |
| | | <template #footer> |
| | | <el-button type="primary" @click="sendForm" :loading="loading"> |
| | | {{ modalOptions.confirmText }} |
| | | </el-button> |
| | | <el-button @click="closeModal">{{ modalOptions.cancelText }}</el-button> |
| | | </template> |
| | | </el-dialog> |
| | | <FormDialog |
| | | v-model="dialogVisible" |
| | | :title="dialogTitle" |
| | | :operationType="operationType" |
| | | width="50%" |
| | | @confirm="sendForm" |
| | | @close="close" |
| | | @cancel="close" |
| | | > |
| | | <el-form :model="form" label-width="100px" :rules="formRules" ref="formRef"> |
| | | <el-form-item label="æ¯åºæ¥æ" prop="expenseDate"> |
| | | <el-date-picker |
| | | style="width: 100%" |
| | | v-model="form.expenseDate" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" |
| | | type="date" |
| | | placeholder="è¯·éæ©æ¥æ" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="æ¯åºç±»å" prop="expenseType"> |
| | | <el-select |
| | | v-model="form.expenseType" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | > |
| | | <el-option :label="item.label" :value="item.value" v-for="(item,index) in expense_types" :key="index" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="ä¾åºååç§°" prop="supplierName"> |
| | | <el-input v-model="form.supplierName" placeholder="请è¾å
¥" /> |
| | | </el-form-item> |
| | | <el-form-item label="æ¯åºéé¢" prop="expenseMoney"> |
| | | <el-input-number :step="0.01" :min="0" style="width: 100%" |
| | | v-model="form.expenseMoney" |
| | | placeholder="请è¾å
¥" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="æ¯åºæè¿°" prop="expenseDescribed"> |
| | | <el-input v-model="form.expenseDescribed" placeholder="请è¾å
¥" /> |
| | | </el-form-item> |
| | | <el-form-item label="仿¬¾æ¹å¼" prop="expenseMethod"> |
| | | <el-select |
| | | v-model="form.expenseMethod" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | > |
| | | <el-option :label="item.label" :value="item.value" v-for="(item,index) in checkout_payment" :key="index" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="å票å·ç " prop="invoiceNumber"> |
| | | <el-input v-model="form.invoiceNumber" placeholder="请è¾å
¥" /> |
| | | </el-form-item> |
| | | <el-form-item label="夿³¨" prop="note"> |
| | | <el-input |
| | | v-model="form.note" |
| | | placeholder="夿³¨" |
| | | /> |
| | | </el-form-item> |
| | | </el-form> |
| | | </FormDialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { useModal } from "@/hooks/useModal"; |
| | | import { add, update } from "@/api/financialManagement/expenseManagement"; |
| | | import Form from "./Form.vue"; |
| | | import { add, update, getAccountExpense } from "@/api/financialManagement/expenseManagement"; |
| | | import { ElMessage } from "element-plus"; |
| | | import useFormData from "@/hooks/useFormData"; |
| | | import FormDialog from "@/components/Dialog/FormDialog.vue"; |
| | | import { ref } from "vue"; |
| | | |
| | | const { proxy } = getCurrentInstance() |
| | | |
| | | defineOptions({ |
| | |
| | | |
| | | const emits = defineEmits(["success"]); |
| | | |
| | | const formRef = ref(); |
| | | const { |
| | | id, |
| | | visible, |
| | | loading, |
| | | openModal, |
| | | modalOptions, |
| | | handleConfirm, |
| | | closeModal, |
| | | } = useModal({ title: "æ¯åº" }); |
| | | const formRef = ref(null); |
| | | const dialogVisible = ref(false); |
| | | const operationType = ref("add"); // add | edit |
| | | const id = ref(undefined); |
| | | const submitting = ref(false); |
| | | |
| | | const dialogTitle = (type) => { |
| | | if (type === "edit") return "ç¼è¾æ¯åº"; |
| | | return "æ°å¢æ¯åº"; |
| | | }; |
| | | |
| | | const { expense_types } = proxy.useDict("expense_types"); |
| | | const { checkout_payment } = proxy.useDict("checkout_payment"); |
| | | |
| | | const formRules = { |
| | | supplierName: [{ required: true, trigger: "blur", message: "请è¾å
¥" }], |
| | | expenseMoney: [{ required: true, trigger: "blur", message: "请è¾å
¥" }], |
| | | expenseDescribed: [{ required: true, trigger: "blur", message: "请è¾å
¥" }], |
| | | expenseDate: [{ required: true, trigger: "change", message: "è¯·éæ©" }], |
| | | expenseType: [{ required: true, trigger: "change", message: "è¯·éæ©" }], |
| | | expenseMethod: [{ required: true, trigger: "change", message: "è¯·éæ©" }], |
| | | } |
| | | |
| | | const { form, resetForm } = useFormData({ |
| | | expenseDate: undefined, // æ¯åºæ¥æ |
| | | expenseType: undefined, // æ¯åºç±»å |
| | | supplierName: undefined, // ä¾åºååç§° |
| | | expenseMoney: undefined, // æ¯åºéé¢ |
| | | expenseDescribed: undefined, // æ¯åºæè¿° |
| | | expenseMethod: undefined, // 仿¬¾æ¹å¼ |
| | | invoiceNumber: undefined, // å票å·ç |
| | | note: undefined, // 夿³¨ |
| | | }); |
| | | |
| | | const sendForm = () => { |
| | | proxy.$refs.formRef.$refs.formRef.validate(async valid => { |
| | | if (valid) { |
| | | const {code} = id.value |
| | | ? await update({id: id.value, ...formRef.value.form}) |
| | | : await add(formRef.value.form); |
| | | if (code == 200) { |
| | | emits("success"); |
| | | ElMessage({message: "æä½æå", type: "success"}); |
| | | close(); |
| | | } else { |
| | | loading.value = false; |
| | | } |
| | | } |
| | | }) |
| | | if (submitting.value) return; |
| | | formRef.value?.validate(async (valid) => { |
| | | if (valid) { |
| | | submitting.value = true; |
| | | try { |
| | | const { code } = id.value |
| | | ? await update({ id: id.value, ...form }) |
| | | : await add(form); |
| | | if (code == 200) { |
| | | emits("success"); |
| | | ElMessage({ message: "æä½æå", type: "success" }); |
| | | close(); |
| | | } |
| | | } finally { |
| | | submitting.value = false; |
| | | } |
| | | } |
| | | }) |
| | | }; |
| | | |
| | | const close = () => { |
| | | formRef.value.resetFormAndValidate(); |
| | | closeModal(); |
| | | resetForm(); |
| | | formRef.value?.clearValidate(); |
| | | id.value = undefined; |
| | | dialogVisible.value = false; |
| | | }; |
| | | |
| | | const loadForm = async (id) => { |
| | | openModal(id); |
| | | await nextTick(); |
| | | formRef.value.loadForm(id); |
| | | const loadForm = async (rowId) => { |
| | | operationType.value = "edit"; |
| | | id.value = rowId; |
| | | dialogVisible.value = true; |
| | | if (rowId) { |
| | | const { code, data } = await getAccountExpense(rowId); |
| | | if (code == 200) { |
| | | form.expenseDate = data.expenseDate; |
| | | form.expenseType = data.expenseType; |
| | | form.supplierName = data.supplierName; |
| | | form.expenseMoney = data.expenseMoney; |
| | | form.expenseDescribed = data.expenseDescribed; |
| | | form.expenseMethod = data.expenseMethod; |
| | | form.invoiceNumber = data.invoiceNumber; |
| | | form.note = data.note; |
| | | } |
| | | } else { |
| | | resetForm(); |
| | | formRef.value?.clearValidate(); |
| | | } |
| | | }; |
| | | |
| | | const openModal = () => { |
| | | operationType.value = "add"; |
| | | id.value = undefined; |
| | | resetForm(); |
| | | formRef.value?.clearValidate(); |
| | | dialogVisible.value = true; |
| | | }; |
| | | |
| | | defineExpose({ |
| | |
| | | <el-button |
| | | type="danger" |
| | | icon="Delete" |
| | | :disabled="multipleList.length <= 0" |
| | | @click="deleteRow(multipleList.map((item) => item.id))" |
| | | :disabled="multipleList.length <= 0 || hasBusinessIdInSelection" |
| | | @click="handleBatchDelete" |
| | | > |
| | | æ¹éå é¤ |
| | | </el-button> |
| | |
| | | @pagination="changePage" |
| | | > |
| | | <template #operation="{ row }"> |
| | | <el-button type="primary" text @click="edit(row.id)" icon="editPen"> |
| | | <el-button |
| | | type="primary" |
| | | link |
| | | :disabled="!!row.businessId" |
| | | @click="edit(row.id)" |
| | | > |
| | | ç¼è¾ |
| | | </el-button> |
| | | <el-button |
| | | type="primary" |
| | | text |
| | | link |
| | | @click="openFilesFormDia(row)" |
| | | > |
| | | éä»¶ |
| | |
| | | </PIMTable> |
| | | </div> |
| | | <Modal ref="modalRef" @success="getTableData"></Modal> |
| | | <files-dia ref="filesDia"></files-dia> |
| | | <FileListDialog |
| | | ref="fileListRef" |
| | | v-model="fileListDialogVisible" |
| | | :show-upload-button="true" |
| | | :show-delete-button="true" |
| | | :upload-method="handleUpload" |
| | | :delete-method="handleFileDelete" |
| | | /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { usePaginationApi } from "@/hooks/usePaginationApi"; |
| | | import { listPage, delAccountExpense } from "@/api/financialManagement/expenseManagement"; |
| | | import { onMounted, getCurrentInstance } from "vue"; |
| | | import { listPage, delAccountExpense, fileListPage, fileAdd, fileDel } from "@/api/financialManagement/expenseManagement"; |
| | | import { onMounted, getCurrentInstance, ref, computed } from "vue"; |
| | | import Modal from "./Modal.vue"; |
| | | import { ElMessageBox, ElMessage } from "element-plus"; |
| | | import dayjs from "dayjs"; |
| | | import FilesDia from "../revenueManagement/filesDia.vue"; |
| | | import FileListDialog from "@/components/Dialog/FileListDialog.vue"; |
| | | import request from "@/utils/request"; |
| | | import { getToken } from "@/utils/auth"; |
| | | |
| | | defineOptions({ |
| | | name: "æ¯åºç®¡ç", |
| | |
| | | const modalRef = ref(); |
| | | const { checkout_payment } = proxy.useDict("checkout_payment"); |
| | | const { expense_types } = proxy.useDict("expense_types"); |
| | | const filesDia = ref() |
| | | const fileListRef = ref(null); |
| | | const fileListDialogVisible = ref(false); |
| | | const currentFileRow = ref(null); |
| | | const accountType = ref('æ¯åº'); |
| | | |
| | | const { |
| | | filters, |
| | |
| | | [ |
| | | { |
| | | label: "æ¯åºæ¥æ", |
| | | align: "center", |
| | | prop: "expenseDate", |
| | | }, |
| | | { |
| | |
| | | }, |
| | | { |
| | | label: "ä¾åºååç§°", |
| | | align: "center", |
| | | prop: "supplierName", |
| | | |
| | | }, |
| | | { |
| | | label: "æ¯åºéé¢", |
| | | align: "center", |
| | | prop: "expenseMoney", |
| | | |
| | | }, |
| | | { |
| | | label: "æ¯åºæè¿°", |
| | | align: "center", |
| | | prop: "expenseDescribed", |
| | | |
| | | }, |
| | |
| | | label: "仿¬¾æ¹å¼", |
| | | align: "center", |
| | | prop: "expenseMethod", |
| | | width: '120', |
| | | dataType: "tag", |
| | | formatData: (params) => { |
| | | if (checkout_payment.value.find((m) => m.value == params)) { |
| | |
| | | }, |
| | | { |
| | | label: "å票å·ç ", |
| | | align: "center", |
| | | prop: "invoiceNumber", |
| | | |
| | | }, |
| | | { |
| | | label: "夿³¨", |
| | | align: "center", |
| | | prop: "note", |
| | | |
| | | }, |
| | | { |
| | | label: "å½å
¥äºº", |
| | | align: "center", |
| | | prop: "inputUser", |
| | | }, |
| | | { |
| | | label: "å½å
¥æ¥æ", |
| | | align: "center", |
| | | prop: "inputTime", |
| | | |
| | | }, |
| | |
| | | dataType: "slot", |
| | | slot: "operation", |
| | | align: "center", |
| | | width: "200px", |
| | | width: "160px", |
| | | }, |
| | | ] |
| | | ); |
| | |
| | | multipleList.value = selectionList; |
| | | }; |
| | | |
| | | // 夿éä¸ç项䏿¯å¦æ businessId |
| | | const hasBusinessIdInSelection = computed(() => { |
| | | return multipleList.value.some(item => item.businessId); |
| | | }); |
| | | |
| | | const add = () => { |
| | | modalRef.value.openModal(); |
| | | }; |
| | | const edit = (id) => { |
| | | // æ£æ¥å½åè¡æ¯å¦æ businessId |
| | | const row = dataList.value.find(item => item.id === id); |
| | | if (row && row.businessId) { |
| | | proxy.$modal.msgWarning("该记å½å·²å
³èä¸å¡ï¼ä¸è½ç¼è¾"); |
| | | return; |
| | | } |
| | | modalRef.value.loadForm(id); |
| | | }; |
| | | const changePage = ({ page, limit }) => { |
| | |
| | | onCurrentChange(page); |
| | | }; |
| | | const deleteRow = (id) => { |
| | | // å¦ææ¯æ°ç»ï¼æ£æ¥æ¯å¦æ businessId |
| | | if (Array.isArray(id)) { |
| | | const hasBusinessId = id.some(itemId => { |
| | | const row = dataList.value.find(item => item.id === itemId); |
| | | return row && row.businessId; |
| | | }); |
| | | if (hasBusinessId) { |
| | | proxy.$modal.msgWarning("éä¸çè®°å½ä¸å
å«å·²å
³èä¸å¡çè®°å½ï¼ä¸è½å é¤"); |
| | | return; |
| | | } |
| | | } else { |
| | | // å个å é¤ï¼æ£æ¥æ¯å¦æ businessId |
| | | const row = dataList.value.find(item => item.id === id); |
| | | if (row && row.businessId) { |
| | | proxy.$modal.msgWarning("该记å½å·²å
³èä¸å¡ï¼ä¸è½å é¤"); |
| | | return; |
| | | } |
| | | } |
| | | |
| | | ElMessageBox.confirm("æ¤æä½å°æ°¸ä¹
å é¤è¯¥æ°æ®, æ¯å¦ç»§ç»?", "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | |
| | | getTableData(); |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | // æ¹éå é¤ |
| | | const handleBatchDelete = () => { |
| | | if (multipleList.value.length === 0) { |
| | | proxy.$modal.msgWarning("è¯·éæ©è¦å é¤çæ°æ®"); |
| | | return; |
| | | } |
| | | |
| | | // æ£æ¥æ¯å¦æ businessId |
| | | if (hasBusinessIdInSelection.value) { |
| | | proxy.$modal.msgWarning("éä¸çè®°å½ä¸å
å«å·²å
³èä¸å¡çè®°å½ï¼ä¸è½å é¤"); |
| | | return; |
| | | } |
| | | |
| | | const ids = multipleList.value.map((item) => item.id); |
| | | deleteRow(ids); |
| | | }; |
| | | |
| | | const changeDaterange = (value) => { |
| | |
| | | }); |
| | | }; |
| | | // æå¼éä»¶å¼¹æ¡ |
| | | const openFilesFormDia = (row) => { |
| | | nextTick(() => { |
| | | filesDia.value?.openDialog( row,'æ¯åº') |
| | | }) |
| | | const openFilesFormDia = async (row) => { |
| | | currentFileRow.value = row; |
| | | accountType.value = 'æ¯åº'; |
| | | try { |
| | | const res = await fileListPage({ |
| | | accountId: row.id, |
| | | accountType: accountType.value, |
| | | current: 1, |
| | | size: 100 |
| | | }); |
| | | if (res.code === 200 && fileListRef.value) { |
| | | // å°æ°æ®è½¬æ¢ä¸º FileListDialog éè¦çæ ¼å¼ |
| | | const fileList = (res.data?.records || []).map(item => ({ |
| | | name: item.name, |
| | | url: item.url, |
| | | id: item.id, |
| | | ...item |
| | | })); |
| | | fileListRef.value.open(fileList); |
| | | fileListDialogVisible.value = true; |
| | | } |
| | | } catch (error) { |
| | | proxy.$modal.msgError("è·åéä»¶å表失败"); |
| | | } |
| | | }; |
| | | |
| | | // ä¸ä¼ éä»¶ |
| | | const handleUpload = async () => { |
| | | if (!currentFileRow.value) { |
| | | proxy.$modal.msgWarning("请å
éæ©æ°æ®"); |
| | | return null; |
| | | } |
| | | |
| | | return new Promise((resolve) => { |
| | | // å建ä¸ä¸ªéèçæä»¶è¾å
¥å
ç´ |
| | | const input = document.createElement('input'); |
| | | input.type = 'file'; |
| | | input.style.display = 'none'; |
| | | input.onchange = async (e) => { |
| | | const file = e.target.files[0]; |
| | | if (!file) { |
| | | resolve(null); |
| | | return; |
| | | } |
| | | |
| | | try { |
| | | // ä½¿ç¨ FormData ä¸ä¼ æä»¶ |
| | | const formData = new FormData(); |
| | | formData.append('file', file); |
| | | |
| | | const uploadRes = await request({ |
| | | url: '/file/upload', |
| | | method: 'post', |
| | | data: formData, |
| | | headers: { |
| | | 'Content-Type': 'multipart/form-data', |
| | | Authorization: `Bearer ${getToken()}` |
| | | } |
| | | }); |
| | | |
| | | if (uploadRes.code === 200) { |
| | | // ä¿åéä»¶ä¿¡æ¯ |
| | | const fileData = { |
| | | accountId: currentFileRow.value.id, |
| | | accountType: accountType.value, |
| | | name: uploadRes.data.originalName || file.name, |
| | | url: uploadRes.data.tempPath || uploadRes.data.url |
| | | }; |
| | | |
| | | const saveRes = await fileAdd(fileData); |
| | | if (saveRes.code === 200) { |
| | | proxy.$modal.msgSuccess("æä»¶ä¸ä¼ æå"); |
| | | // éæ°å è½½æä»¶å表 |
| | | const listRes = await fileListPage({ |
| | | accountId: currentFileRow.value.id, |
| | | accountType: accountType.value, |
| | | current: 1, |
| | | size: 100 |
| | | }); |
| | | if (listRes.code === 200 && fileListRef.value) { |
| | | const fileList = (listRes.data?.records || []).map(item => ({ |
| | | name: item.name, |
| | | url: item.url, |
| | | id: item.id, |
| | | ...item |
| | | })); |
| | | fileListRef.value.setList(fileList); |
| | | } |
| | | // è¿åæ°æä»¶ä¿¡æ¯ |
| | | resolve({ |
| | | name: fileData.name, |
| | | url: fileData.url, |
| | | id: saveRes.data?.id |
| | | }); |
| | | } else { |
| | | proxy.$modal.msgError(saveRes.msg || "æä»¶ä¿å失败"); |
| | | resolve(null); |
| | | } |
| | | } else { |
| | | proxy.$modal.msgError(uploadRes.msg || "æä»¶ä¸ä¼ 失败"); |
| | | resolve(null); |
| | | } |
| | | } catch (error) { |
| | | proxy.$modal.msgError("æä»¶ä¸ä¼ 失败"); |
| | | resolve(null); |
| | | } finally { |
| | | document.body.removeChild(input); |
| | | } |
| | | }; |
| | | |
| | | document.body.appendChild(input); |
| | | input.click(); |
| | | }); |
| | | }; |
| | | |
| | | // å é¤éä»¶ |
| | | const handleFileDelete = async (row) => { |
| | | try { |
| | | const res = await fileDel([row.id]); |
| | | if (res.code === 200) { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | // éæ°å è½½æä»¶å表 |
| | | if (currentFileRow.value && fileListRef.value) { |
| | | const listRes = await fileListPage({ |
| | | accountId: currentFileRow.value.id, |
| | | accountType: accountType.value, |
| | | current: 1, |
| | | size: 100 |
| | | }); |
| | | if (listRes.code === 200) { |
| | | const fileList = (listRes.data?.records || []).map(item => ({ |
| | | name: item.name, |
| | | url: item.url, |
| | | id: item.id, |
| | | ...item |
| | | })); |
| | | fileListRef.value.setList(fileList); |
| | | } |
| | | } |
| | | return true; // è¿å true 表示å 餿åï¼ç»ä»¶ä¼æ´æ°å表 |
| | | } else { |
| | | proxy.$modal.msgError(res.msg || "å é¤å¤±è´¥"); |
| | | return false; |
| | | } |
| | | } catch (error) { |
| | | proxy.$modal.msgError("å é¤å¤±è´¥"); |
| | | return false; |
| | | } |
| | | }; |
| | | |
| | | onMounted(() => { |
| | |
| | | <template> |
| | | <div style="padding: 20px;"> |
| | | <!-- 页颿 é¢åæ¥æçé --> |
| | | <!-- 页颿 é¢åæä»½çé --> |
| | | <div class="w-full md:w-auto flex items-center gap-3" style="margin-bottom: 20px;"> |
| | | <el-date-picker |
| | | v-model="dateRange" |
| | | type="daterange" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" |
| | | type="monthrange" |
| | | format="YYYY-MM" |
| | | value-format="YYYY-MM" |
| | | range-separator="è³" |
| | | start-placeholder="å¼å§æ¥æ" |
| | | end-placeholder="ç»ææ¥æ" |
| | | clearable |
| | | start-placeholder="å¼å§æä»½" |
| | | end-placeholder="ç»ææä»½" |
| | | :disabled-date="disabledDate" |
| | | @change="handleDateChange" |
| | | class="w-full md:w-auto" |
| | | style="margin-right: 30px;" |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, computed, onMounted, reactive } from 'vue'; |
| | | import { ref, computed, onMounted, reactive, nextTick, getCurrentInstance } from 'vue'; |
| | | import 'element-plus/dist/index.css'; |
| | | import Echarts from "@/components/Echarts/echarts.vue"; |
| | | import { reportForms,reportIncome,reportExpense } from "@/api/financialManagement/financialStatements"; |
| | |
| | | |
| | | // æ¥æèå´ |
| | | const dateRange = ref(null); |
| | | const { proxy } = getCurrentInstance(); |
| | | const chartStyle = { |
| | | width: '100%', |
| | | height: '100%', // 设置å¾è¡¨å®¹å¨çé«åº¦ |
| | |
| | | return `<div>${axisLabel}</div><div>${rows}</div>` |
| | | } |
| | | }) |
| | | const months = ['1æ','2æ','3æ','4æ','5æ','6æ','7æ','8æ','9æ','10æ','11æ','12æ']; |
| | | const lineSeries0 = ref([]) |
| | | const lineSeries1 = ref([]) |
| | | |
| | | // æ ¹æ®æä»½èå´çæ x è½´æ°æ® |
| | | const generateMonthLabels = (startMonth, endMonth) => { |
| | | const labels = []; |
| | | let current = dayjs(startMonth); |
| | | const end = dayjs(endMonth); |
| | | |
| | | while (current.isBefore(end) || current.isSame(end, 'month')) { |
| | | labels.push(`${current.month() + 1}æ`); |
| | | current = current.add(1, 'month'); |
| | | } |
| | | |
| | | return labels; |
| | | }; |
| | | |
| | | const xAxis0 = ref([ |
| | | { |
| | | type: 'category', |
| | | axisTick: { show: true, alignWithLabel: true }, |
| | | data: months, |
| | | data: [], |
| | | }, |
| | | ]); |
| | | const xAxis1 = ref([ |
| | | { |
| | | type: 'category', |
| | | axisTick: { show: true, alignWithLabel: true }, |
| | | data: months, |
| | | data: [], |
| | | }, |
| | | ]); |
| | | const yAxis0 = [ |
| | |
| | | left: '60%', |
| | | orient: 'vertical', |
| | | icon: 'circle', |
| | | data: pieData0.value.map(item => item.name), |
| | | data: (pieData0.value || []).filter(item => item && item.name).map(item => item.name), |
| | | formatter: function(name) { |
| | | const item = pieData0.value.find(i => i.name === name); |
| | | if (!name) return ''; |
| | | const item = pieData0.value.find(i => i && i.name === name); |
| | | if (!item) return name; |
| | | return `${name} | ${item.percent} ${item.amount}`; |
| | | }, |
| | |
| | | left: '60%', |
| | | orient: 'vertical', |
| | | icon: 'circle', |
| | | data: pieData1.value.map(item => item.name), |
| | | data: (pieData1.value || []).filter(item => item && item.name).map(item => item.name), |
| | | formatter: function(name) { |
| | | const item = pieData1.value.find(i => i.name === name); |
| | | if (!name) return ''; |
| | | const item = pieData1.value.find(i => i && i.name === name); |
| | | if (!item) return name; |
| | | return `${name} | ${item.percent} ${item.amount}`; |
| | | }, |
| | |
| | | label: { |
| | | show: false |
| | | }, |
| | | data: pieData0.value, |
| | | data: (pieData0.value || []).filter(item => item && item.name), |
| | | color: pieColors |
| | | } |
| | | ]); |
| | |
| | | label: { |
| | | show: false |
| | | }, |
| | | data: pieData1.value, |
| | | data: (pieData1.value || []).filter(item => item && item.name), |
| | | color: pieColors |
| | | } |
| | | ]); |
| | |
| | | const pageInfo = ref({ |
| | | }) |
| | | |
| | | // è·åæè¿å
个æçèå´ |
| | | const getLastSixMonths = () => { |
| | | const endMonth = dayjs().format('YYYY-MM'); |
| | | const startMonth = dayjs().subtract(5, 'month').format('YYYY-MM'); |
| | | return [startMonth, endMonth]; |
| | | }; |
| | | |
| | | const getData = async () => { |
| | | if (!dateRange.value || !dateRange.value.length) { |
| | | if (!dateRange.value || !Array.isArray(dateRange.value) || dateRange.value.length !== 2) { |
| | | return; |
| | | } |
| | | const startDateStr = dateRange.value[0]; |
| | | const endDateStr = dateRange.value[1]; |
| | | if (!startDateStr || !endDateStr) { |
| | | return; |
| | | } |
| | | |
| | | // éªè¯æ¥ææ ¼å¼å¹¶è½¬æ¢ä¸ºå®æ´æ¥æ |
| | | const startDate = dayjs(startDateStr); |
| | | const endDate = dayjs(endDateStr); |
| | | if (!startDate.isValid() || !endDate.isValid()) { |
| | | console.error('æ æçæ¥ææ ¼å¼'); |
| | | return; |
| | | } |
| | | |
| | | // æ´æ° x è½´æ°æ® |
| | | const monthLabels = generateMonthLabels(startDateStr, endDateStr); |
| | | xAxis0.value[0].data = monthLabels; |
| | | xAxis1.value[0].data = monthLabels; |
| | | |
| | | // å¼å§æä»½æ¼æ¥ç¬¬ä¸å¤©ï¼ç»ææä»½æ¼æ¥æåä¸å¤© |
| | | const entryDateStart = startDate.startOf('month').format('YYYY-MM-DD'); |
| | | const entryDateEnd = endDate.endOf('month').format('YYYY-MM-DD'); |
| | | |
| | | try { |
| | | const {code,data} = await reportForms({entryDateStart:dateRange.value[0], entryDateEnd:dateRange.value[1]}); |
| | | if(code === 200) { |
| | | pageInfo.value = data |
| | | pieData0.value = data.incomeType.map(item=>({ |
| | | name:item.typeName, |
| | | value:item.account, |
| | | percent:`${item.proportion*100}%`, |
| | | amount:`Â¥${item.account}` |
| | | const {code,data} = await reportForms({entryDateStart, entryDateEnd}); |
| | | if(code === 200 && data) { |
| | | pageInfo.value = data || {}; |
| | | // å®å
¨å¤çæ°æ®ï¼è¿æ»¤æ null æ undefined |
| | | pieData0.value = (data.incomeType || []).filter(item => item && item.typeName).map(item=>({ |
| | | name:item.typeName || '', |
| | | value:item.account || 0, |
| | | percent:`${((item.proportion || 0) * 100).toFixed(2)}%`, |
| | | amount:`Â¥${(item.account || 0).toFixed(2)}` |
| | | })) |
| | | pieData1.value = data.expenseType.map(item=>({ |
| | | name:item.typeName, |
| | | value:item.account, |
| | | percent:`${item.proportion*100}%`, |
| | | amount:`Â¥${item.account}` |
| | | pieData1.value = (data.expenseType || []).filter(item => item && item.typeName).map(item=>({ |
| | | name:item.typeName || '', |
| | | value:item.account || 0, |
| | | percent:`${((item.proportion || 0) * 100).toFixed(2)}%`, |
| | | amount:`Â¥${(item.account || 0).toFixed(2)}` |
| | | })) |
| | | |
| | | } |
| | | } catch (error) { |
| | | console.error('è·åè´¢å¡ææ æ°æ®å¤±è´¥ï¼', error); |
| | | } |
| | | try{ |
| | | const {code,data} = await reportIncome(); |
| | | if(code==200){ |
| | | lineSeries0.value = data.map(item=>({ |
| | | name:item.typeName, |
| | | const {code,data} = await reportIncome({entryDateStart, entryDateEnd}); |
| | | if(code==200 && data && Array.isArray(data)){ |
| | | lineSeries0.value = data.filter(item => item && item.typeName).map(item=>({ |
| | | name:item.typeName || '', |
| | | type: 'line', |
| | | data:item.account.map(item=>Number(item)) |
| | | data:(item.account || []).map(val => Number(val) || 0) |
| | | })) |
| | | |
| | | } |
| | | }catch (error) { |
| | | console.error('è·åè´¢å¡ææ æ°æ®å¤±è´¥ï¼', error); |
| | | } |
| | | try{ |
| | | const {code,data} = await reportExpense(); |
| | | if(code==200){ |
| | | lineSeries1.value = data.map(item=>({ |
| | | name:item.typeName, |
| | | const {code,data} = await reportExpense({entryDateStart, entryDateEnd}); |
| | | if(code==200 && data && Array.isArray(data)){ |
| | | lineSeries1.value = data.filter(item => item && item.typeName).map(item=>({ |
| | | name:item.typeName || '', |
| | | type: 'line', |
| | | data:item.account.map(item=>Number(item)) |
| | | data:(item.account || []).map(val => Number(val) || 0) |
| | | })) |
| | | |
| | | } |
| | | }catch (error) { |
| | | console.error('è·åè´¢å¡ææ æ°æ®å¤±è´¥ï¼', error); |
| | |
| | | |
| | | // åå§å |
| | | onMounted(() => { |
| | | // ä¸è®¾ç½®é»è®¤æ¥æï¼ç±ç¨æ·æå¨éæ© |
| | | // 设置é»è®¤å¼ä¸ºæè¿å
个æ |
| | | const defaultRange = getLastSixMonths(); |
| | | dateRange.value = defaultRange; |
| | | // ä½¿ç¨ nextTick ç¡®ä¿ç»ä»¶å®å
¨æ¸²æååè°ç¨ |
| | | nextTick(() => { |
| | | getData(); |
| | | }); |
| | | }); |
| | | |
| | | // å¤çæ¥æèå´åå |
| | | const handleDateChange = (newRange) => { |
| | | dateRange.value = newRange; |
| | | if (newRange && newRange.length === 2) { |
| | | getData() |
| | | // é嶿份鿩èå´ï¼æå¤12个æï¼ |
| | | const disabledDate = (time) => { |
| | | // å¦ææ²¡æéæ©å¼å§æä»½ï¼ä¸ç¦ç¨ä»»ä½æ¥æ |
| | | if (!dateRange.value || !Array.isArray(dateRange.value) || !dateRange.value[0]) { |
| | | return false; |
| | | } |
| | | |
| | | const startMonth = dayjs(dateRange.value[0]); |
| | | const currentMonth = dayjs(time); |
| | | |
| | | // 妿å½åæä»½å¨å¼å§æä»½ä¹åï¼ç¦ç¨ |
| | | if (currentMonth.isBefore(startMonth, 'month')) { |
| | | return true; |
| | | } |
| | | |
| | | // è®¡ç®æå¤§å
许çæä»½ï¼å¼å§æä»½ + 11个æ = 12个æï¼ |
| | | const maxMonth = startMonth.add(11, 'month'); |
| | | |
| | | // ç¦ç¨è¶
è¿12个æçæä»½ |
| | | return currentMonth.isAfter(maxMonth, 'month'); |
| | | }; |
| | | |
| | | // éç½®æ¥æèå´ |
| | | // å¤çæä»½èå´åå |
| | | const handleDateChange = (newRange) => { |
| | | if (!newRange || !Array.isArray(newRange) || newRange.length !== 2) { |
| | | return; |
| | | } |
| | | |
| | | // éªè¯æä»½èå´ä¸è¶
è¿12个æ |
| | | const startDate = dayjs(newRange[0]); |
| | | const endDate = dayjs(newRange[1]); |
| | | const monthDiff = endDate.diff(startDate, 'month'); |
| | | |
| | | if (monthDiff > 11) { |
| | | proxy.$modal.msgWarning('æå¤åªè½éæ©12个æä»½'); |
| | | // èªå¨è°æ´ä¸º12个æ |
| | | const adjustedEnd = startDate.add(11, 'month').format('YYYY-MM'); |
| | | dateRange.value = [newRange[0], adjustedEnd]; |
| | | getData(); |
| | | return; |
| | | } |
| | | |
| | | dateRange.value = newRange; |
| | | getData(); |
| | | }; |
| | | |
| | | // éç½®æä»½èå´ |
| | | const resetDateRange = () => { |
| | | dateRange.value = null; |
| | | // é置为æè¿å
个æ |
| | | dateRange.value = getLastSixMonths(); |
| | | getData(); |
| | | }; |
| | | |
| | | </script> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <FormDialog |
| | | v-model="dialogVisible" |
| | | :title="dialogTitle" |
| | | :operationType="operationType" |
| | | width="60%" |
| | | @confirm="sendForm" |
| | | @close="close" |
| | | @cancel="close" |
| | | > |
| | | <el-form |
| | | ref="formRef" |
| | | :model="form" |
| | | :rules="formRules" |
| | | label-width="120px" |
| | | > |
| | | <el-form-item label="忬¾äººå§å" prop="borrowerName"> |
| | | <el-input v-model="form.borrowerName" placeholder="请è¾å
¥å款人å§å" /> |
| | | </el-form-item> |
| | | <el-form-item label="忬¾éé¢ï¼å
ï¼" prop="borrowAmount"> |
| | | <el-input-number |
| | | :step="0.01" |
| | | :min="0" |
| | | :precision="2" |
| | | style="width: 100%" |
| | | v-model="form.borrowAmount" |
| | | placeholder="请è¾å
¥å款éé¢" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="忬¾å©çï¼%ï¼" prop="interestRate"> |
| | | <el-input-number |
| | | :step="0.01" |
| | | :min="0" |
| | | :precision="2" |
| | | style="width: 100%" |
| | | v-model="form.interestRate" |
| | | placeholder="请è¾å
¥å款å©çï¼å¦ï¼5.85" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="忬¾æ¥æ" prop="borrowDate"> |
| | | <el-date-picker |
| | | style="width: 100%" |
| | | v-model="form.borrowDate" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" |
| | | type="date" |
| | | placeholder="è¯·éæ©åæ¬¾æ¥æ" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | <!-- å®é
è¿æ¬¾æ¥æï¼ä»
âè¿æ¬¾âæ¶å¯å¡« --> |
| | | <el-form-item |
| | | v-if="operationType === 'repay'" |
| | | label="å®é
è¿æ¬¾æ¥æ" |
| | | prop="repayDate" |
| | | > |
| | | <el-date-picker |
| | | style="width: 100%" |
| | | v-model="form.repayDate" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" |
| | | type="date" |
| | | placeholder="è¯·éæ©å®é
è¿æ¬¾æ¥æï¼è¿æ¬¾åå¡«åï¼" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="夿³¨" prop="remark"> |
| | | <el-input |
| | | v-model="form.remark" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请è¾å
¥å¤æ³¨ï¼å款说æï¼" |
| | | /> |
| | | </el-form-item> |
| | | </el-form> |
| | | </FormDialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { add, update } from "@/api/financialManagement/loanManagement"; |
| | | import useFormData from "@/hooks/useFormData"; |
| | | import FormDialog from "@/components/Dialog/FormDialog.vue"; |
| | | import { ElMessage } from "element-plus"; |
| | | import { ref } from "vue"; |
| | | |
| | | defineOptions({ |
| | | name: "忬¾æ°å¢ç¼è¾", |
| | | }); |
| | | |
| | | const emits = defineEmits(["success"]); |
| | | |
| | | const formRef = ref(null); |
| | | const dialogVisible = ref(false); |
| | | const operationType = ref("add"); // add | edit |
| | | const id = ref(undefined); |
| | | const submitting = ref(false); |
| | | |
| | | const dialogTitle = (type) => { |
| | | if (type === "edit") return "ç¼è¾å款"; |
| | | if (type === "repay") return "è¿æ¬¾"; |
| | | return "æ°å¢å款"; |
| | | }; |
| | | |
| | | const formRules = { |
| | | borrowerName: [{ required: true, trigger: "blur", message: "请è¾å
¥å款人å§å" }], |
| | | borrowAmount: [{ required: true, trigger: "blur", message: "请è¾å
¥å款éé¢" }], |
| | | interestRate: [{ required: true, trigger: "blur", message: "请è¾å
¥å款å©ç" }], |
| | | borrowDate: [{ required: true, trigger: "change", message: "è¯·éæ©åæ¬¾æ¥æ" }], |
| | | repayDate: [ |
| | | { |
| | | validator: (_rule, value, callback) => { |
| | | if (operationType.value === "repay" && !value) { |
| | | callback(new Error("è¯·éæ©å®é
è¿æ¬¾æ¥æ")); |
| | | return; |
| | | } |
| | | callback(); |
| | | }, |
| | | trigger: "change", |
| | | }, |
| | | ], |
| | | }; |
| | | |
| | | const { form, resetForm } = useFormData({ |
| | | borrowerName: undefined, // 忬¾äººå§å |
| | | borrowAmount: undefined, // 忬¾éé¢ï¼å
ï¼ |
| | | interestRate: undefined, // 忬¾å©çï¼å¦ï¼5.85 代表5.85%ï¼ |
| | | borrowDate: undefined, // 忬¾æ¥æ |
| | | repayDate: undefined, // å®é
è¿æ¬¾æ¥æï¼è¿æ¬¾åå¡«å
ï¼ |
| | | remark: undefined, // 夿³¨ï¼å款说æï¼ |
| | | }); |
| | | |
| | | const sendForm = () => { |
| | | if (submitting.value) return; |
| | | formRef.value?.validate(async (valid) => { |
| | | if (valid) { |
| | | submitting.value = true; |
| | | try { |
| | | const isRepay = operationType.value === "repay"; |
| | | // è¿æ¬¾ï¼ä¸å±ç¤º statusï¼ä½æäº¤æ¶å¼ºå¶ä¼ status=2ï¼èµ°æ´æ°æ¥å£ |
| | | const payload = isRepay |
| | | ? { id: id.value, ...form, status: 2 } |
| | | : id.value |
| | | ? { id: id.value, ...form } |
| | | : form; |
| | | |
| | | const { code } = isRepay |
| | | ? await update(payload) |
| | | : id.value |
| | | ? await update(payload) |
| | | : await add(payload); |
| | | if (code == 200) { |
| | | emits("success"); |
| | | ElMessage({ message: "æä½æå", type: "success" }); |
| | | close(); |
| | | } |
| | | } finally { |
| | | submitting.value = false; |
| | | } |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | const close = () => { |
| | | resetForm(); |
| | | formRef.value?.clearValidate(); |
| | | id.value = undefined; |
| | | dialogVisible.value = false; |
| | | }; |
| | | |
| | | // ç¼è¾ï¼ç´æ¥ç¨åè¡¨è¡æ°æ®åå¡«ï¼é¿å
ä¾èµè¯¦æ
æ¥å£ï¼ |
| | | const loadForm = async (row) => { |
| | | const rowId = row?.id; |
| | | operationType.value = "edit"; |
| | | id.value = rowId; |
| | | dialogVisible.value = true; |
| | | if (rowId) { |
| | | form.borrowerName = row.borrowerName; |
| | | form.borrowAmount = row.borrowAmount; |
| | | form.interestRate = row.interestRate; |
| | | form.borrowDate = row.borrowDate; |
| | | form.repayDate = row.repayDate; |
| | | form.remark = row.remark; |
| | | } else { |
| | | resetForm(); |
| | | formRef.value?.clearValidate(); |
| | | } |
| | | }; |
| | | |
| | | // è¿æ¬¾ï¼æå¼å¼¹çªï¼ä»
å¡«åå®é
è¿æ¬¾æ¥æï¼æäº¤æ¶å¼ºå¶ status=2 |
| | | const repay = async (row) => { |
| | | const rowId = row?.id; |
| | | operationType.value = "repay"; |
| | | id.value = rowId; |
| | | dialogVisible.value = true; |
| | | if (rowId) { |
| | | // 为äºèµ° update æ¥å£æ´ç¨³å¦¥ï¼å¸¦ä¸åææ°æ®ï¼åªè®©ç¨æ·é repayDate |
| | | form.borrowerName = row.borrowerName; |
| | | form.borrowAmount = row.borrowAmount; |
| | | form.interestRate = row.interestRate; |
| | | form.borrowDate = row.borrowDate; |
| | | form.remark = row.remark; |
| | | form.repayDate = undefined; |
| | | } else { |
| | | resetForm(); |
| | | formRef.value?.clearValidate(); |
| | | } |
| | | }; |
| | | |
| | | const openModal = () => { |
| | | operationType.value = "add"; |
| | | id.value = undefined; |
| | | resetForm(); |
| | | formRef.value?.clearValidate(); |
| | | dialogVisible.value = true; |
| | | }; |
| | | |
| | | defineExpose({ |
| | | openModal, |
| | | loadForm, |
| | | repay, |
| | | }); |
| | | </script> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <el-form :model="filters" :inline="true"> |
| | | <el-form-item label="忬¾äººå§å:"> |
| | | <el-input |
| | | v-model="filters.borrowerName" |
| | | placeholder="请è¾å
¥å款人å§å" |
| | | clearable |
| | | style="width: 200px;" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="忬¾æ¥æ:"> |
| | | <el-date-picker |
| | | v-model="filters.borrowDate" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="daterange" |
| | | range-separator="è³" |
| | | start-placeholder="å¼å§æ¥æ" |
| | | end-placeholder="ç»ææ¥æ" |
| | | clearable |
| | | @change="changeDaterange" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="忬¾ç¶æ:"> |
| | | <el-select |
| | | v-model="filters.status" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | style="width: 200px;" |
| | | > |
| | | <el-option label="å¾
è¿æ¬¾" :value="1" /> |
| | | <el-option label="å·²è¿æ¬¾" :value="2" /> |
| | | </el-select> |
| | | </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 @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> |
| | | </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" |
| | | > |
| | | <template #operation="{ row }"> |
| | | <el-button type="primary" link @click="edit(row)"> |
| | | ç¼è¾ |
| | | </el-button> |
| | | <el-button |
| | | :disabled="row.status !== 1" |
| | | type="primary" |
| | | link |
| | | @click="repay(row)" |
| | | > |
| | | è¿æ¬¾ |
| | | </el-button> |
| | | </template> |
| | | </PIMTable> |
| | | </div> |
| | | <Modal ref="modalRef" @success="getTableData"></Modal> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { usePaginationApi } from "@/hooks/usePaginationApi"; |
| | | import { listPage, delAccountLoan } from "@/api/financialManagement/loanManagement"; |
| | | import { onMounted, getCurrentInstance, ref, nextTick } from "vue"; |
| | | import Modal from "./Modal.vue"; |
| | | import { ElMessageBox, ElMessage } from "element-plus"; |
| | | import dayjs from "dayjs"; |
| | | |
| | | defineOptions({ |
| | | name: "忬¾ç®¡ç", |
| | | }); |
| | | |
| | | // è¡¨æ ¼å¤éæ¡éä¸é¡¹ |
| | | const multipleList = ref([]); |
| | | const { proxy } = getCurrentInstance(); |
| | | const modalRef = ref(); |
| | | |
| | | const { |
| | | filters, |
| | | columns, |
| | | dataList, |
| | | pagination, |
| | | getTableData, |
| | | resetFilters, |
| | | onCurrentChange, |
| | | } = usePaginationApi( |
| | | listPage, |
| | | { |
| | | borrowerName: undefined, |
| | | borrowDate: undefined, |
| | | status: undefined, |
| | | }, |
| | | [ |
| | | { |
| | | label: "忬¾äººå§å", |
| | | prop: "borrowerName", |
| | | }, |
| | | { |
| | | label: "忬¾éé¢ï¼å
ï¼", |
| | | prop: "borrowAmount", |
| | | formatData: (val) => { |
| | | return val ? `Â¥${parseFloat(val).toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}` : 'Â¥0.00'; |
| | | }, |
| | | }, |
| | | { |
| | | label: "忬¾å©çï¼%ï¼", |
| | | prop: "interestRate", |
| | | formatData: (val) => { |
| | | return val ? `${parseFloat(val).toFixed(2)}%` : '-'; |
| | | }, |
| | | }, |
| | | { |
| | | label: "忬¾æ¥æ", |
| | | prop: "borrowDate", |
| | | }, |
| | | { |
| | | label: "å®é
è¿æ¬¾æ¥æ", |
| | | prop: "repayDate", |
| | | }, |
| | | { |
| | | label: "忬¾ç¶æ", |
| | | prop: "status", |
| | | dataType: "tag", |
| | | align: 'center', |
| | | formatData: (params) => { |
| | | if (params == 1) { |
| | | return "å¾
è¿æ¬¾"; |
| | | } else if (params == 2) { |
| | | return "å·²è¿æ¬¾"; |
| | | } |
| | | return null; |
| | | }, |
| | | formatType: (params) => { |
| | | if (params == 1) { |
| | | return "error"; |
| | | } else if (params == 2) { |
| | | return "success"; |
| | | } |
| | | return null; |
| | | }, |
| | | }, |
| | | { |
| | | fixed: "right", |
| | | label: "æä½", |
| | | dataType: "slot", |
| | | slot: "operation", |
| | | align: "center", |
| | | width: "120px", |
| | | }, |
| | | ], |
| | | null, |
| | | { |
| | | // å°åç«¯åæ¬¾æ¥æèå´è½¬æ¢ä¸ºå端éè¦ç entryDateStart / entryDateEndï¼å¹¶ä¸ä¸ä¼ borrowDate |
| | | borrowDate: (val) => { |
| | | if (val && val.length === 2) { |
| | | return { |
| | | entryDateStart: dayjs(val[0]).format("YYYY-MM-DD"), |
| | | entryDateEnd: dayjs(val[1]).format("YYYY-MM-DD"), |
| | | }; |
| | | } |
| | | return {}; |
| | | }, |
| | | } |
| | | ); |
| | | |
| | | // å¤éååä»ä¹ |
| | | const handleSelectionChange = (selectionList) => { |
| | | multipleList.value = selectionList; |
| | | }; |
| | | |
| | | const add = () => { |
| | | modalRef.value.openModal(); |
| | | }; |
| | | |
| | | const edit = (row) => { |
| | | modalRef.value.loadForm(row); |
| | | }; |
| | | |
| | | const repay = (row) => { |
| | | modalRef.value.repay(row); |
| | | }; |
| | | |
| | | const changePage = ({ page, limit }) => { |
| | | pagination.currentPage = page; |
| | | pagination.pageSize = limit; |
| | | onCurrentChange(page); |
| | | }; |
| | | |
| | | const deleteRow = (id) => { |
| | | ElMessageBox.confirm("æ¤æä½å°æ°¸ä¹
å é¤è¯¥æ°æ®, æ¯å¦ç»§ç»?", "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }).then(async () => { |
| | | const { code } = await delAccountLoan(id); |
| | | if (code == 200) { |
| | | ElMessage({ |
| | | type: "success", |
| | | message: "å 餿å", |
| | | }); |
| | | getTableData(); |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | const changeDaterange = (value) => { |
| | | if (value) { |
| | | filters.borrowDate = value; |
| | | } else { |
| | | filters.borrowDate = null; |
| | | } |
| | | getTableData(); |
| | | }; |
| | | |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | proxy.download(`/borrowInfo/export`, {}, "忬¾å°è´¦.xlsx"); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getTableData(); |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .table_list { |
| | | margin-top: unset; |
| | | } |
| | | .actions { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | margin-bottom: 10px; |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <el-dialog :title="modalOptions.title" v-model="visible" @close="close" width="30%"> |
| | | <Form ref="formRef"></Form> |
| | | <template #footer> |
| | | <el-button type="primary" @click="sendForm" :loading="loading"> |
| | | {{ modalOptions.confirmText }} |
| | | </el-button> |
| | | <el-button @click="closeModal">{{ modalOptions.cancelText }}</el-button> |
| | | </template> |
| | | </el-dialog> |
| | | <FormDialog |
| | | v-model="dialogVisible" |
| | | :title="dialogTitle" |
| | | :operationType="operationType" |
| | | width="30%" |
| | | @confirm="sendForm" |
| | | @close="close" |
| | | @cancel="close" |
| | | > |
| | | <el-form :model="form" label-width="100px" :rules="formRules" ref="formRef"> |
| | | <el-form-item label="æ¶å
¥æ¥æ" prop="incomeDate"> |
| | | <el-date-picker |
| | | style="width: 100%" |
| | | v-model="form.incomeDate" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" |
| | | type="date" |
| | | placeholder="è¯·éæ©æ¥æ" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="æ¶å
¥ç±»å" prop="incomeType"> |
| | | <el-select |
| | | v-model="form.incomeType" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | > |
| | | <el-option :label="item.label" :value="item.value" v-for="(item,index) in income_types" :key="index" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="客æ·åç§°" prop="customerName"> |
| | | <el-input v-model="form.customerName" placeholder="请è¾å
¥" /> |
| | | </el-form-item> |
| | | <el-form-item label="æ¶å
¥éé¢" prop="incomeMoney"> |
| | | <el-input-number :step="0.01" :min="0" style="width: 100%" |
| | | v-model="form.incomeMoney" |
| | | placeholder="请è¾å
¥" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="æ¶å
¥æè¿°" prop="incomeDescribed"> |
| | | <el-input v-model="form.incomeDescribed" placeholder="请è¾å
¥" /> |
| | | </el-form-item> |
| | | <el-form-item label="æ¶æ¬¾æ¹å¼" prop="incomeMethod"> |
| | | <el-select |
| | | v-model="form.incomeMethod" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | > |
| | | <el-option :label="item.label" :value="item.value" v-for="(item,index) in payment_methods" :key="index" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="å票å·ç " prop="invoiceNumber"> |
| | | <el-input v-model="form.invoiceNumber" placeholder="请è¾å
¥" /> |
| | | </el-form-item> |
| | | <el-form-item label="夿³¨" prop="note"> |
| | | <el-input |
| | | v-model="form.note" |
| | | placeholder="夿³¨" |
| | | /> |
| | | </el-form-item> |
| | | </el-form> |
| | | </FormDialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { useModal } from "@/hooks/useModal"; |
| | | import { add, update } from "@/api/financialManagement/revenueManagement"; |
| | | import Form from "./Form.vue"; |
| | | import { add, update, getAccountIncome } from "@/api/financialManagement/revenueManagement"; |
| | | import { ElMessage } from "element-plus"; |
| | | import useFormData from "@/hooks/useFormData"; |
| | | import FormDialog from "@/components/Dialog/FormDialog.vue"; |
| | | import { ref } from "vue"; |
| | | |
| | | const { proxy } = getCurrentInstance() |
| | | |
| | | defineOptions({ |
| | |
| | | |
| | | const emits = defineEmits(["success"]); |
| | | |
| | | const formRef = ref(); |
| | | const { |
| | | id, |
| | | visible, |
| | | loading, |
| | | openModal, |
| | | modalOptions, |
| | | handleConfirm, |
| | | closeModal, |
| | | } = useModal({ title: "æ¶å
¥" }); |
| | | const formRef = ref(null); |
| | | const dialogVisible = ref(false); |
| | | const operationType = ref("add"); // add | edit |
| | | const id = ref(undefined); |
| | | const submitting = ref(false); |
| | | |
| | | const dialogTitle = (type) => { |
| | | if (type === "edit") return "ç¼è¾æ¶å
¥"; |
| | | return "æ°å¢æ¶å
¥"; |
| | | }; |
| | | |
| | | const { income_types } = proxy.useDict("income_types"); |
| | | const { payment_methods } = proxy.useDict("payment_methods"); |
| | | |
| | | const formRules = { |
| | | customerName: [{ required: true, trigger: "blur", message: "请è¾å
¥" }], |
| | | incomeMoney: [{ required: true, trigger: "blur", message: "请è¾å
¥" }], |
| | | incomeDescribed: [{ required: true, trigger: "blur", message: "请è¾å
¥" }], |
| | | incomeDate: [{ required: true, trigger: "change", message: "è¯·éæ©" }], |
| | | incomeType: [{ required: true, trigger: "change", message: "è¯·éæ©" }], |
| | | incomeMethod: [{ required: true, trigger: "change", message: "è¯·éæ©" }], |
| | | } |
| | | |
| | | const { form, resetForm } = useFormData({ |
| | | incomeDate: undefined, // æ¶å
¥æ¥æ |
| | | incomeType: undefined, // æ¶å
¥ç±»å |
| | | customerName: undefined, // 客æ·åç§° |
| | | incomeMoney: undefined, // æ¶å
¥éé¢ |
| | | incomeDescribed: undefined, // æ¶å
¥æè¿° |
| | | incomeMethod: undefined, // æ¶æ¬¾æ¹å¼ |
| | | invoiceNumber: undefined, // å票å·ç |
| | | note: undefined, // 夿³¨ |
| | | }); |
| | | |
| | | const sendForm = () => { |
| | | proxy.$refs.formRef.$refs.formRef.validate(async valid => { |
| | | if (valid) { |
| | | const {code} = id.value |
| | | ? await update({id: id.value, ...formRef.value.form}) |
| | | : await add(formRef.value.form); |
| | | if (code == 200) { |
| | | emits("success"); |
| | | ElMessage({message: "æä½æå", type: "success"}); |
| | | close(); |
| | | } else { |
| | | loading.value = false; |
| | | } |
| | | } |
| | | }) |
| | | if (submitting.value) return; |
| | | formRef.value?.validate(async (valid) => { |
| | | if (valid) { |
| | | submitting.value = true; |
| | | try { |
| | | const { code } = id.value |
| | | ? await update({ id: id.value, ...form }) |
| | | : await add(form); |
| | | if (code == 200) { |
| | | emits("success"); |
| | | ElMessage({ message: "æä½æå", type: "success" }); |
| | | close(); |
| | | } |
| | | } finally { |
| | | submitting.value = false; |
| | | } |
| | | } |
| | | }) |
| | | }; |
| | | |
| | | const close = () => { |
| | | formRef.value.resetFormAndValidate(); |
| | | closeModal(); |
| | | resetForm(); |
| | | formRef.value?.clearValidate(); |
| | | id.value = undefined; |
| | | dialogVisible.value = false; |
| | | }; |
| | | |
| | | const loadForm = async (id) => { |
| | | openModal(id); |
| | | await nextTick(); |
| | | formRef.value.loadForm(id); |
| | | const loadForm = async (rowId) => { |
| | | operationType.value = "edit"; |
| | | id.value = rowId; |
| | | dialogVisible.value = true; |
| | | if (rowId) { |
| | | const { code, data } = await getAccountIncome(rowId); |
| | | if (code == 200) { |
| | | form.incomeDate = data.incomeDate; |
| | | form.incomeType = data.incomeType; |
| | | form.customerName = data.customerName; |
| | | form.incomeMoney = data.incomeMoney; |
| | | form.incomeDescribed = data.incomeDescribed; |
| | | form.incomeMethod = data.incomeMethod; |
| | | form.invoiceNumber = data.invoiceNumber; |
| | | form.note = data.note; |
| | | } |
| | | } else { |
| | | resetForm(); |
| | | formRef.value?.clearValidate(); |
| | | } |
| | | }; |
| | | |
| | | const openModal = () => { |
| | | operationType.value = "add"; |
| | | id.value = undefined; |
| | | resetForm(); |
| | | formRef.value?.clearValidate(); |
| | | dialogVisible.value = true; |
| | | }; |
| | | |
| | | defineExpose({ |
| | |
| | | <el-button |
| | | type="danger" |
| | | icon="Delete" |
| | | :disabled="multipleList.length <= 0" |
| | | @click="deleteRow(multipleList.map((item) => item.id))" |
| | | :disabled="multipleList.length <= 0 || hasBusinessIdInSelection" |
| | | @click="handleBatchDelete" |
| | | > |
| | | æ¹éå é¤ |
| | | </el-button> |
| | |
| | | @pagination="changePage" |
| | | > |
| | | <template #operation="{ row }"> |
| | | <el-button type="primary" text @click="edit(row.id)" icon="editPen"> |
| | | <el-button |
| | | type="primary" |
| | | link |
| | | :disabled="!!row.businessId" |
| | | @click="edit(row.id)" |
| | | > |
| | | ç¼è¾ |
| | | </el-button> |
| | | <el-button |
| | | type="primary" |
| | | text |
| | | link |
| | | @click="openFilesFormDia(row)" |
| | | > |
| | | éä»¶ |
| | |
| | | </PIMTable> |
| | | </div> |
| | | <Modal ref="modalRef" @success="getTableData"></Modal> |
| | | <files-dia ref="filesDia"></files-dia> |
| | | <FileListDialog |
| | | ref="fileListRef" |
| | | v-model="fileListDialogVisible" |
| | | :show-upload-button="true" |
| | | :show-delete-button="true" |
| | | :upload-method="handleUpload" |
| | | :delete-method="handleFileDelete" |
| | | /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { usePaginationApi } from "@/hooks/usePaginationApi"; |
| | | import { listPage, delAccountIncome } from "@/api/financialManagement/revenueManagement"; |
| | | import { onMounted, getCurrentInstance } from "vue"; |
| | | import { listPage, delAccountIncome, fileListPage, fileAdd, fileDel } from "@/api/financialManagement/revenueManagement"; |
| | | import { onMounted, getCurrentInstance, ref, computed } from "vue"; |
| | | import Modal from "./Modal.vue"; |
| | | import { ElMessageBox, ElMessage } from "element-plus"; |
| | | import dayjs from "dayjs"; |
| | | import FilesDia from "./filesDia.vue"; |
| | | import FileListDialog from "@/components/Dialog/FileListDialog.vue"; |
| | | import request from "@/utils/request"; |
| | | import { getToken } from "@/utils/auth"; |
| | | |
| | | defineOptions({ |
| | | name: "æ¶å
¥ç®¡ç", |
| | |
| | | const modalRef = ref(); |
| | | const { payment_methods } = proxy.useDict("payment_methods"); |
| | | const { income_types } = proxy.useDict("income_types"); |
| | | const filesDia = ref() |
| | | const fileListRef = ref(null); |
| | | const fileListDialogVisible = ref(false); |
| | | const currentFileRow = ref(null); |
| | | const accountType = ref('æ¶å
¥'); |
| | | |
| | | const { |
| | | filters, |
| | |
| | | [ |
| | | { |
| | | label: "æ¶å
¥æ¥æ", |
| | | align: "center", |
| | | prop: "incomeDate", |
| | | }, |
| | | { |
| | | label: "æ¶å
¥ç±»å", |
| | | align: "center", |
| | | prop: "incomeType", |
| | | dataType: "tag", |
| | | formatData: (params) => { |
| | |
| | | }, |
| | | { |
| | | label: "客æ·åç§°", |
| | | align: "center", |
| | | prop: "customerName", |
| | | width: '200' |
| | | |
| | | }, |
| | | { |
| | | label: "æ¶å
¥éé¢", |
| | | align: "center", |
| | | prop: "incomeMoney", |
| | | |
| | | }, |
| | | { |
| | | label: "æ¶å
¥æè¿°", |
| | | align: "center", |
| | | prop: "incomeDescribed", |
| | | |
| | | }, |
| | | { |
| | | label: "æ¶æ¬¾æ¹å¼", |
| | | align: "center", |
| | | prop: "incomeMethod", |
| | | align: 'center', |
| | | width: '100', |
| | | dataType: "tag", |
| | | formatData: (params) => { |
| | | if (payment_methods.value.find((m) => m.value == params)) { |
| | |
| | | }, |
| | | { |
| | | label: "å票å·ç ", |
| | | align: "center", |
| | | prop: "invoiceNumber", |
| | | |
| | | }, |
| | | { |
| | | label: "夿³¨", |
| | | align: "center", |
| | | prop: "note", |
| | | |
| | | }, |
| | | { |
| | | label: "å½å
¥äºº", |
| | | align: "center", |
| | | prop: "inputUser", |
| | | }, |
| | | { |
| | | label: "å½å
¥æ¥æ", |
| | | align: "center", |
| | | prop: "inputTime", |
| | | |
| | | }, |
| | |
| | | dataType: "slot", |
| | | slot: "operation", |
| | | align: "center", |
| | | width: "200px", |
| | | width: "160px", |
| | | }, |
| | | ] |
| | | ); |
| | |
| | | multipleList.value = selectionList; |
| | | }; |
| | | |
| | | // 夿éä¸ç项䏿¯å¦æ businessId |
| | | const hasBusinessIdInSelection = computed(() => { |
| | | return multipleList.value.some(item => item.businessId); |
| | | }); |
| | | |
| | | const add = () => { |
| | | modalRef.value.openModal(); |
| | | }; |
| | | const edit = (id) => { |
| | | // æ£æ¥å½åè¡æ¯å¦æ businessId |
| | | const row = dataList.value.find(item => item.id === id); |
| | | if (row && row.businessId) { |
| | | proxy.$modal.msgWarning("该记å½å·²å
³èä¸å¡ï¼ä¸è½ç¼è¾"); |
| | | return; |
| | | } |
| | | modalRef.value.loadForm(id); |
| | | }; |
| | | const changePage = ({ page, limit }) => { |
| | |
| | | onCurrentChange(page); |
| | | }; |
| | | const deleteRow = (id) => { |
| | | // å¦ææ¯æ°ç»ï¼æ£æ¥æ¯å¦æ businessId |
| | | if (Array.isArray(id)) { |
| | | const hasBusinessId = id.some(itemId => { |
| | | const row = dataList.value.find(item => item.id === itemId); |
| | | return row && row.businessId; |
| | | }); |
| | | if (hasBusinessId) { |
| | | proxy.$modal.msgWarning("éä¸çè®°å½ä¸å
å«å·²å
³èä¸å¡çè®°å½ï¼ä¸è½å é¤"); |
| | | return; |
| | | } |
| | | } else { |
| | | // å个å é¤ï¼æ£æ¥æ¯å¦æ businessId |
| | | const row = dataList.value.find(item => item.id === id); |
| | | if (row && row.businessId) { |
| | | proxy.$modal.msgWarning("该记å½å·²å
³èä¸å¡ï¼ä¸è½å é¤"); |
| | | return; |
| | | } |
| | | } |
| | | |
| | | ElMessageBox.confirm("æ¤æä½å°æ°¸ä¹
å é¤è¯¥æ°æ®, æ¯å¦ç»§ç»?", "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | |
| | | getTableData(); |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | // æ¹éå é¤ |
| | | const handleBatchDelete = () => { |
| | | if (multipleList.value.length === 0) { |
| | | proxy.$modal.msgWarning("è¯·éæ©è¦å é¤çæ°æ®"); |
| | | return; |
| | | } |
| | | |
| | | // æ£æ¥æ¯å¦æ businessId |
| | | if (hasBusinessIdInSelection.value) { |
| | | proxy.$modal.msgWarning("éä¸çè®°å½ä¸å
å«å·²å
³èä¸å¡çè®°å½ï¼ä¸è½å é¤"); |
| | | return; |
| | | } |
| | | |
| | | const ids = multipleList.value.map((item) => item.id); |
| | | deleteRow(ids); |
| | | }; |
| | | |
| | | const changeDaterange = (value) => { |
| | |
| | | }); |
| | | }; |
| | | // æå¼éä»¶å¼¹æ¡ |
| | | const openFilesFormDia = (row) => { |
| | | nextTick(() => { |
| | | filesDia.value?.openDialog( row,'æ¶å
¥') |
| | | }) |
| | | const openFilesFormDia = async (row) => { |
| | | currentFileRow.value = row; |
| | | accountType.value = 'æ¶å
¥'; |
| | | try { |
| | | const res = await fileListPage({ |
| | | accountId: row.id, |
| | | accountType: accountType.value, |
| | | current: 1, |
| | | size: 100 |
| | | }); |
| | | if (res.code === 200 && fileListRef.value) { |
| | | // å°æ°æ®è½¬æ¢ä¸º FileListDialog éè¦çæ ¼å¼ |
| | | const fileList = (res.data?.records || []).map(item => ({ |
| | | name: item.name, |
| | | url: item.url, |
| | | id: item.id, |
| | | ...item |
| | | })); |
| | | fileListRef.value.open(fileList); |
| | | fileListDialogVisible.value = true; |
| | | } |
| | | } catch (error) { |
| | | proxy.$modal.msgError("è·åéä»¶å表失败"); |
| | | } |
| | | }; |
| | | |
| | | // ä¸ä¼ éä»¶ |
| | | const handleUpload = async () => { |
| | | if (!currentFileRow.value) { |
| | | proxy.$modal.msgWarning("请å
éæ©æ°æ®"); |
| | | return null; |
| | | } |
| | | |
| | | return new Promise((resolve) => { |
| | | // å建ä¸ä¸ªéèçæä»¶è¾å
¥å
ç´ |
| | | const input = document.createElement('input'); |
| | | input.type = 'file'; |
| | | input.style.display = 'none'; |
| | | input.onchange = async (e) => { |
| | | const file = e.target.files[0]; |
| | | if (!file) { |
| | | resolve(null); |
| | | return; |
| | | } |
| | | |
| | | try { |
| | | // ä½¿ç¨ FormData ä¸ä¼ æä»¶ |
| | | const formData = new FormData(); |
| | | formData.append('file', file); |
| | | |
| | | const uploadRes = await request({ |
| | | url: '/file/upload', |
| | | method: 'post', |
| | | data: formData, |
| | | headers: { |
| | | 'Content-Type': 'multipart/form-data', |
| | | Authorization: `Bearer ${getToken()}` |
| | | } |
| | | }); |
| | | |
| | | if (uploadRes.code === 200) { |
| | | // ä¿åéä»¶ä¿¡æ¯ |
| | | const fileData = { |
| | | accountId: currentFileRow.value.id, |
| | | accountType: accountType.value, |
| | | name: uploadRes.data.originalName || file.name, |
| | | url: uploadRes.data.tempPath || uploadRes.data.url |
| | | }; |
| | | |
| | | const saveRes = await fileAdd(fileData); |
| | | if (saveRes.code === 200) { |
| | | proxy.$modal.msgSuccess("æä»¶ä¸ä¼ æå"); |
| | | // éæ°å è½½æä»¶å表 |
| | | const listRes = await fileListPage({ |
| | | accountId: currentFileRow.value.id, |
| | | accountType: accountType.value, |
| | | current: 1, |
| | | size: 100 |
| | | }); |
| | | if (listRes.code === 200 && fileListRef.value) { |
| | | const fileList = (listRes.data?.records || []).map(item => ({ |
| | | name: item.name, |
| | | url: item.url, |
| | | id: item.id, |
| | | ...item |
| | | })); |
| | | fileListRef.value.setList(fileList); |
| | | } |
| | | // è¿åæ°æä»¶ä¿¡æ¯ |
| | | resolve({ |
| | | name: fileData.name, |
| | | url: fileData.url, |
| | | id: saveRes.data?.id |
| | | }); |
| | | } else { |
| | | proxy.$modal.msgError(saveRes.msg || "æä»¶ä¿å失败"); |
| | | resolve(null); |
| | | } |
| | | } else { |
| | | proxy.$modal.msgError(uploadRes.msg || "æä»¶ä¸ä¼ 失败"); |
| | | resolve(null); |
| | | } |
| | | } catch (error) { |
| | | proxy.$modal.msgError("æä»¶ä¸ä¼ 失败"); |
| | | resolve(null); |
| | | } finally { |
| | | document.body.removeChild(input); |
| | | } |
| | | }; |
| | | |
| | | document.body.appendChild(input); |
| | | input.click(); |
| | | }); |
| | | }; |
| | | |
| | | // å é¤éä»¶ |
| | | const handleFileDelete = async (row) => { |
| | | try { |
| | | const res = await fileDel([row.id]); |
| | | if (res.code === 200) { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | // éæ°å è½½æä»¶å表 |
| | | if (currentFileRow.value && fileListRef.value) { |
| | | const listRes = await fileListPage({ |
| | | accountId: currentFileRow.value.id, |
| | | accountType: accountType.value, |
| | | current: 1, |
| | | size: 100 |
| | | }); |
| | | if (listRes.code === 200) { |
| | | const fileList = (listRes.data?.records || []).map(item => ({ |
| | | name: item.name, |
| | | url: item.url, |
| | | id: item.id, |
| | | ...item |
| | | })); |
| | | fileListRef.value.setList(fileList); |
| | | } |
| | | } |
| | | return true; // è¿å true 表示å 餿åï¼ç»ä»¶ä¼æ´æ°å表 |
| | | } else { |
| | | proxy.$modal.msgError(res.msg || "å é¤å¤±è´¥"); |
| | | return false; |
| | | } |
| | | } catch (error) { |
| | | proxy.$modal.msgError("å é¤å¤±è´¥"); |
| | | return false; |
| | | } |
| | | }; |
| | | |
| | | onMounted(() => { |
| | |
| | | <div class="app-container"> |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title">ä¾åºååç§°ï¼</span> |
| | | <el-input |
| | | v-model="searchForm.supplierName" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥" |
| | | @change="handleQuery" |
| | | clearable |
| | | prefix-icon="Search" |
| | | /> |
| | | <span class="search_title ml10">åºåºæ¥æï¼</span> |
| | | <el-date-picker |
| | | v-model="searchForm.timeStr" |
| | |
| | | > |
| | | </div> |
| | | <div> |
| | | <!-- <el-button type="primary" @click="openForm('add')">æ°å¢</el-button> --> |
| | | <el-button @click="handleOut">导åº</el-button> |
| | | <el-button type="danger" plain @click="handleDelete">å é¤</el-button> |
| | | <el-button type="primary" plain @click="handlePrint">æå°</el-button> |
| | |
| | | @selection-change="handleSelectionChange" |
| | | :expand-row-keys="expandedRowKeys" |
| | | :row-key="(row) => row.id" |
| | | show-summary |
| | | style="width: 100%" |
| | | :summary-method="summarizeMainTable" |
| | | height="calc(100vh - 18.5em)" |
| | | > |
| | | <el-table-column align="center" type="selection" width="55" /> |
| | | <el-table-column align="center" label="åºå·" type="index" width="60" /> |
| | | <el-table-column |
| | | label="åºåºæ¹æ¬¡" |
| | | prop="outboundBatches" |
| | | min-width="100" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | | label="åºåºæ¥æ" |
| | | prop="createTime" |
| | | min-width="250" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | | label="ä¾åºååç§°" |
| | | prop="supplierName" |
| | | width="250" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | | label="产å大类" |
| | | prop="productCategory" |
| | | width="100" |
| | | prop="productName" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | | label="è§æ ¼åå·" |
| | | prop="specificationModel" |
| | | width="100" |
| | | prop="model" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | | label="åä½" |
| | | prop="unit" |
| | | width="80" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | | label="åºåºæ°é" |
| | | prop="inboundNum" |
| | | width="100" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | | label="å«ç¨åä»·(å
)" |
| | | prop="taxInclusiveUnitPrice" |
| | | width="100" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | | label="å«ç¨æ»ä»·(å
)" |
| | | prop="taxInclusiveTotalPrice" |
| | | width="100" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | | label="ç¨ç(%)" |
| | | prop="taxRate" |
| | | width="100" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | | label="ä¸å«ç¨æ»ä»·(å
)" |
| | | prop="taxExclusiveTotalPrice" |
| | | width="180" |
| | | prop="stockOutNum" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | | label="åºåºäºº" |
| | | prop="createBy" |
| | | width="80" |
| | | show-overflow-tooltip |
| | | /> |
| | | <!-- <el-table-column |
| | | fixed="right" |
| | | label="æä½" |
| | | min-width="60" |
| | | align="center" |
| | | > |
| | | <template #default="scope"> |
| | | <el-button |
| | | link |
| | | type="primary" |
| | | size="small" |
| | | @click="openForm('edit', scope.row)" |
| | | >ç¼è¾</el-button |
| | | > |
| | | </template> |
| | | </el-table-column> --> |
| | | </el-table> |
| | | <pagination |
| | | v-show="total > 0" |
| | |
| | | @pagination="paginationChange" |
| | | /> |
| | | </div> |
| | | |
| | | <!-- æå°é¢è§å¼¹çª --> |
| | | <el-dialog |
| | | v-model="printPreviewVisible" |
| | | title="æå°é¢è§" |
| | | width="90%" |
| | | :close-on-click-modal="false" |
| | | class="print-preview-dialog" |
| | | > |
| | | <div class="print-preview-container"> |
| | | <div class="print-preview-header"> |
| | | <el-button type="primary" @click="executePrint">æ§è¡æå°</el-button> |
| | | <el-button @click="printPreviewVisible = false">å
³éé¢è§</el-button> |
| | | </div> |
| | | <div class="print-preview-content"> |
| | | <div v-if="printData.length === 0" style="text-align: center; padding: 50px; color: #999;"> |
| | | ææ æå°æ°æ® |
| | | </div> |
| | | <div v-else style="text-align: center; padding: 10px; color: #666; font-size: 14px; background: #e8f4fd; margin-bottom: 10px;"> |
| | | å
± {{ printData.length }} æ¡æ°æ®å¾
æå° |
| | | </div> |
| | | <div v-for="(item, index) in printData" :key="index" class="print-page"> |
| | | <div class="delivery-note"> |
| | | <div class="header"> |
| | | <div class="company-name">é¼è¯çå®ä¸æé责任å
¬å¸</div> |
| | | <div class="document-title">é¶å®åè´§å</div> |
| | | </div> |
| | | |
| | | <div class="info-section"> |
| | | <div class="info-row"> |
| | | <div> |
| | | <span class="label">åè´§æ¥æï¼</span> |
| | | <span class="value">{{ formatDate(item.createTime) }}</span> |
| | | </div> |
| | | <div> |
| | | |
| | | <span class="label">客æ·åç§°ï¼</span> |
| | | <span class="value">{{ item.supplierName || 'å¼ ç±æ' }}</span> |
| | | </div> |
| | | </div> |
| | | <div class="info-row"> |
| | | <span class="label">åå·ï¼</span> |
| | | <span class="value">{{ item.code }}</span> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="table-section"> |
| | | <table class="product-table"> |
| | | <thead> |
| | | <tr> |
| | | <th>产ååç§°</th> |
| | | <th>è§æ ¼åå·</th> |
| | | <th>åä½</th> |
| | | <th>åä»·</th> |
| | | <th>é¶å®æ°é</th> |
| | | <th>é¶å®éé¢</th> |
| | | </tr> |
| | | </thead> |
| | | <tbody> |
| | | <tr> |
| | | <td>{{ item.productCategory || 'ç ç°ç ' }}</td> |
| | | <td>{{ item.specificationModel || 'æ å' }}</td> |
| | | <td>{{ item.unit || 'å' }}</td> |
| | | <td>{{ item.taxInclusiveUnitPrice || '0' }}</td> |
| | | <td>{{ item.inboundNum || '2000' }}</td> |
| | | <td>{{ item.taxInclusiveTotalPrice || '0' }}</td> |
| | | </tr> |
| | | </tbody> |
| | | <tfoot> |
| | | <tr> |
| | | <td class="label">å计</td> |
| | | <td class="total-value"></td> |
| | | <td class="total-value"></td> |
| | | <td class="total-value"></td> |
| | | <td class="total-value">{{ item.inboundNum || '2000' }}</td> |
| | | <td class="total-value">{{ item.taxInclusiveTotalPrice || '0' }}</td> |
| | | </tr> |
| | | </tfoot> |
| | | </table> |
| | | </div> |
| | | |
| | | <div class="footer-section"> |
| | | <div class="footer-row"> |
| | | <div class="footer-item"> |
| | | <span class="label">æ¶è´§çµè¯ï¼</span> |
| | | <span class="value"></span> |
| | | </div> |
| | | <div class="footer-item"> |
| | | <span class="label">æ¶è´§äººï¼</span> |
| | | <span class="value"></span> |
| | | </div> |
| | | <div class="footer-item address-item"> |
| | | <span class="label">æ¶è´§å°åï¼</span> |
| | | <span class="value address-value"></span> |
| | | </div> |
| | | </div> |
| | | <div class="footer-row"> |
| | | <div class="footer-item"> |
| | | <span class="label">æä½åï¼</span> |
| | | <span class="value">{{ userStore.nickName || 'æå¼å' }}</span> |
| | | </div> |
| | | <div class="footer-item"> |
| | | <span class="label">æå°æ¥æï¼</span> |
| | | <span class="value">{{ formatDateTime(new Date()) }}</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </el-dialog> |
| | | |
| | | |
| | | </div> |
| | | </template> |
| | | |
| | |
| | | }; |
| | | const expandedRowKeys = ref([]); |
| | | |
| | | // 主表åè®¡æ¹æ³ |
| | | const summarizeMainTable = (param) => { |
| | | return proxy.summarizeTable(param, [ |
| | | "contractAmount", |
| | | "taxInclusiveTotalPrice", |
| | | "taxExclusiveTotalPrice", |
| | | ]); |
| | | }; |
| | | |
| | | // å¯¼åº |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | delStockOut({ids:ids}).then((res) => { |
| | | delStockOut(ids).then((res) => { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | getList(); |
| | | }); |
| | |
| | | </thead> |
| | | <tbody> |
| | | <tr> |
| | | <td>${item.productCategory || 'ç ç°ç '}</td> |
| | | <td>${item.specificationModel || 'æ å'}</td> |
| | | <td>${item.productName || 'ç ç°ç '}</td> |
| | | <td>${item.model || 'æ å'}</td> |
| | | <td>${item.unit || 'å'}</td> |
| | | <td>${item.taxInclusiveUnitPrice || '0'}</td> |
| | | <td>${item.inboundNum || '2000'}</td> |
| | |
| | | <div class="app-container"> |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title">ä¾åºååç§°ï¼</span> |
| | | <el-input v-model="searchForm.supplierName" style="width: 240px" placeholder="请è¾å
¥" @change="handleQuery" |
| | | clearable prefix-icon="Search" /> |
| | | <span class="search_title ml10">å
¥åºæ¥æï¼</span> |
| | | <el-date-picker |
| | | v-model="searchForm.timeStr" |
| | | type="date" |
| | | placeholder="è¯·éæ©æ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | clearable |
| | | @change="handleQuery" |
| | | /> |
| | | <el-button type="primary" @click="handleQuery" style="margin-left: 10px">æç´¢</el-button> |
| | | <el-date-picker v-model="searchForm.timeStr" |
| | | type="date" |
| | | placeholder="è¯·éæ©æ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | clearable |
| | | @change="handleQuery"/> |
| | | <span class="search_title ml10">产å大类ï¼</span> |
| | | <el-input v-model="searchForm.productName" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥" |
| | | clearable/> |
| | | <el-button type="primary" |
| | | @click="handleQuery" |
| | | style="margin-left: 10px">æç´¢ |
| | | </el-button> |
| | | </div> |
| | | <div> |
| | | <el-button type="primary" @click="openForm('add')">æ°å¢å
¥åº</el-button> |
| | | <el-button @click="handleOut">导åº</el-button> |
| | | <el-button type="danger" plain @click="handleDelete">å é¤</el-button> |
| | | <el-button type="danger" |
| | | plain |
| | | @click="handleDelete">å é¤ |
| | | </el-button> |
| | | </div> |
| | | </div> |
| | | <div class="table_list"> |
| | | <el-table :data="tableData" border v-loading="tableLoading" @selection-change="handleSelectionChange" |
| | | :expand-row-keys="expandedRowKeys" :row-key="row => row.id" show-summary style="width: 100%" |
| | | :summary-method="summarizeMainTable" height="calc(100vh - 18.5em)"> |
| | | <el-table-column align="center" type="selection" width="55" /> |
| | | <el-table-column align="center" label="åºå·" type="index" width="60" /> |
| | | <el-table-column label="å
¥åºæ¶é´" prop="createTime" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="å
¥åºæ¹æ¬¡" prop="inboundBatches" width="160" show-overflow-tooltip /> |
| | | <el-table-column label="ä¾åºååç§°" prop="supplierName" width="240" show-overflow-tooltip /> |
| | | <el-table-column label="产å大类" prop="productCategory" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="è§æ ¼åå·" prop="specificationModel" width="200" show-overflow-tooltip /> |
| | | <el-table-column label="åä½" prop="unit" width="70" show-overflow-tooltip /> |
| | | <el-table-column label="å
¥åºæ°é" prop="inboundNum" width="90" show-overflow-tooltip /> |
| | | <el-table-column label="å«ç¨åä»·" prop="taxInclusiveUnitPrice" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="å«ç¨æ»ä»·" prop="taxInclusiveTotalPrice" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="ç¨ç(%)" prop="taxRate" width="80" show-overflow-tooltip /> |
| | | <el-table-column label="ä¸å«ç¨æ»ä»·" prop="taxExclusiveTotalPrice" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="å
¥åºäºº" prop="createBy" width="80" show-overflow-tooltip /> |
| | | <el-table-column fixed="right" label="æä½" min-width="60" align="center"> |
| | | <template #default="scope"> |
| | | <el-button link type="primary" size="small" @click="openForm('edit', scope.row);">ç¼è¾</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table :data="tableData" |
| | | border |
| | | v-loading="tableLoading" |
| | | @selection-change="handleSelectionChange" |
| | | :expand-row-keys="expandedRowKeys" |
| | | :row-key="row => row.id" |
| | | show-summary |
| | | style="width: 100%" |
| | | :summary-method="summarizeMainTable" |
| | | height="calc(100vh - 18.5em)"> |
| | | <el-table-column align="center" |
| | | type="selection" |
| | | width="55"/> |
| | | <el-table-column align="center" |
| | | label="åºå·" |
| | | type="index" |
| | | width="60"/> |
| | | <el-table-column label="å
¥åºæ¹æ¬¡" |
| | | prop="inboundBatches" |
| | | width="280" |
| | | show-overflow-tooltip/> |
| | | <el-table-column label="å
¥åºæ¶é´" |
| | | prop="createTime" |
| | | show-overflow-tooltip/> |
| | | <el-table-column label="产å大类" |
| | | prop="productName" |
| | | show-overflow-tooltip/> |
| | | <el-table-column label="è§æ ¼åå·" |
| | | prop="model" |
| | | show-overflow-tooltip/> |
| | | <el-table-column label="åä½" |
| | | prop="unit" |
| | | show-overflow-tooltip/> |
| | | <el-table-column label="å
¥åºæ°é" |
| | | prop="stockInNum" |
| | | show-overflow-tooltip/> |
| | | <el-table-column label="å
¥åºäºº" |
| | | prop="createBy" |
| | | show-overflow-tooltip/> |
| | | </el-table> |
| | | <pagination v-show="total > 0" :total="total" layout="total, sizes, prev, pager, next, jumper" |
| | | :page="page.current" :limit="page.size" @pagination="paginationChange" /> |
| | | <pagination v-show="total > 0" |
| | | :total="total" |
| | | layout="total, sizes, prev, pager, next, jumper" |
| | | :page="page.current" |
| | | :limit="page.size" |
| | | @pagination="pageProductChange"/> |
| | | </div> |
| | | |
| | | <el-dialog v-model="dialogFormVisible" :title="operationType === 'add' ? 'æ°å¢å
¥åº' : 'ç¼è¾å
¥åº'" width="70%" |
| | | @close="closeDia"> |
| | | <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef"> |
| | | <el-form-item label="éè´è®¢åå·" prop="purchaseContractNumber"> |
| | | <el-select |
| | | v-model="form.purchaseContractNumber" |
| | | placeholder="è¯·éæ©éè´è®¢åå·" |
| | | clearable |
| | | filterable |
| | | remote |
| | | :remote-method="loadPurchaseOptions" |
| | | :loading="loadingPurchaseOptions" |
| | | @change="handlePurchaseChange" |
| | | :disabled="operationType === 'edit'" |
| | | style="width: 100%" |
| | | > |
| | | <el-option |
| | | v-for="item in purchaseOptions" |
| | | :key="item.purchaseContractNumber" |
| | | :label="formatPurchaseOption(item)" |
| | | :value="item.purchaseContractNumber" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-table |
| | | :data="productList" |
| | | border |
| | | v-loading="loadingProducts" |
| | | @selection-change="handleSelectionChange" |
| | | > |
| | | <el-table-column align="center" type="selection" width="55" /> |
| | | <el-table-column |
| | | align="center" |
| | | label="åºå·" |
| | | type="index" |
| | | width="60" |
| | | /> |
| | | <el-table-column label="产å大类" prop="productCategory" /> |
| | | <el-table-column label="è§æ ¼åå·" prop="specificationModel" /> |
| | | <el-table-column label="åä½" prop="unit" width="70" /> |
| | | <el-table-column label="ä¾åºå" prop="supplierName" width="100" /> |
| | | <el-table-column label="éè´æ°é" prop="quantity" width="100" /> |
| | | <el-table-column label="å¾
å
¥åºæ°é" prop="quantity0" width="100" /> |
| | | <el-table-column label="æ¬æ¬¡å
¥åºæ°é" prop="quantityStock" width="150"> |
| | | <template #default="scope"> |
| | | <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="scope.row.quantityStock" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="ç¨ç(%)" prop="taxRate" width="120" /> |
| | | <el-table-column |
| | | label="å«ç¨åä»·(å
)" |
| | | prop="taxInclusiveUnitPrice" |
| | | :formatter="formattedNumber" |
| | | width="150" |
| | | /> |
| | | <el-table-column |
| | | label="å«ç¨æ»ä»·(å
)" |
| | | prop="taxInclusiveTotalPrice" |
| | | :formatter="formattedNumber" |
| | | width="150" |
| | | /> |
| | | <el-table-column |
| | | label="ä¸å«ç¨æ»ä»·(å
)" |
| | | prop="taxExclusiveTotalPrice" |
| | | :formatter="formattedNumber" |
| | | width="150" |
| | | /> |
| | | </el-table> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="submitForm">确认</el-button> |
| | | <el-button @click="closeDia">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import pagination from '@/components/PIMTable/Pagination.vue' |
| | | import { ref, reactive, toRefs, onMounted, getCurrentInstance } from 'vue' |
| | | import { ElMessageBox } from "element-plus"; |
| | | import useUserStore from '@/store/modules/user' |
| | | import pagination from "@/components/PIMTable/Pagination.vue"; |
| | | import { |
| | | getStockInPage, |
| | | updateStockIn, |
| | | addSutockIn, |
| | | delStockIn, |
| | | selectProductRecordListByPuechaserId |
| | | } from "@/api/inventoryManagement/stockIn.js"; |
| | | import { purchaseListPage } from "@/api/procurementManagement/procurementLedger.js"; |
| | | import { getCurrentDate } from "@/utils/index.js"; |
| | | ref, |
| | | reactive, |
| | | toRefs, |
| | | onMounted, |
| | | getCurrentInstance, |
| | | nextTick, |
| | | } from "vue"; |
| | | import {ElMessageBox} from "element-plus"; |
| | | import { |
| | | getStockInRecordListPage, |
| | | batchDeleteStockInRecords, |
| | | } from "@/api/inventoryManagement/stockInRecord.js"; |
| | | |
| | | const userStore = useUserStore() |
| | | const { proxy } = getCurrentInstance() |
| | | const {proxy} = getCurrentInstance(); |
| | | |
| | | const tableData = ref([]) |
| | | const selectedRows = ref([]) |
| | | const userList = ref([]) |
| | | |
| | | const purchaseOptions = ref([]) |
| | | const loadingPurchaseOptions = ref(false) |
| | | |
| | | |
| | | const loading = ref(false); |
| | | const tableLoading = ref(false) |
| | | const tableData = ref([]); |
| | | const selectedRows = ref([]); |
| | | const tableLoading = ref(false); |
| | | const activeTab = ref("production"); // å½åæ¿æ´»ç tab |
| | | |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | }) |
| | | const total = ref(0) |
| | | }); |
| | | const total = ref(0); |
| | | |
| | | // ç¨æ·ä¿¡æ¯è¡¨åå¼¹æ¡æ°æ® |
| | | const operationType = ref('')// æä½ç±»å: 'add' æ 'edit' |
| | | const dialogFormVisible = ref(false)// å¼¹æ¡æ¾ç¤ºç¶æ |
| | | const productList = ref([]);// 产ååè¡¨æ°æ® |
| | | const loadingProducts = ref(false);// 产åå è½½ç¶æ |
| | | const productSelectedRows = ref([]) // 产åè¡¨æ ¼éä¸è¡ |
| | | const data = reactive({ |
| | | searchForm: { |
| | | supplierName: '', |
| | | timeStr: '', |
| | | productName: "", |
| | | timeStr: "", |
| | | }, |
| | | form: { |
| | | id: null, |
| | | purchaseContractNumber: '', // éè´è®¢åå· |
| | | supplierId: null, // ä¾åºåID |
| | | supplierName: '', // ä¾åºååç§° |
| | | inboundTime: '', // å
¥åºæ¶é´ |
| | | inboundBatch: '', // å
¥åºæ¹æ¬¡ |
| | | recorderId: userStore.userId, // å½å
¥äººID |
| | | recorderName: userStore.name, // å½å
¥äººå§å |
| | | entryDate: getCurrentDate(), // å½å
¥æ¥æ |
| | | remark: '', // 夿³¨ |
| | | }, |
| | | rules: { |
| | | purchaseContractNumber: [{ required: true, message: "请è¾å
¥éè´ååå·", trigger: "blur" }], |
| | | supplierId: [{ required: true, message: "è¯·éæ©ä¾åºå", trigger: "change" }], |
| | | inboundTime: [{ required: true, message: "è¯·éæ©å
¥åºæ¶é´", trigger: "change" }], |
| | | inboundBatch: [{ required: true, message: "请è¾å
¥å
¥åºæ¹æ¬¡", trigger: "blur" }] |
| | | } |
| | | }) |
| | | const { searchForm, form, rules } = toRefs(data) |
| | | |
| | | const formatPurchaseOption = (item = {}) => { |
| | | const contract = item.purchaseContractNumber || '--'; |
| | | const supplier = item.supplierName ? ` · ${item.supplierName}` : ''; |
| | | return `${contract}${supplier}`; |
| | | }; |
| | | |
| | | const loadPurchaseOptions = async (keyword = '') => { |
| | | try { |
| | | loadingPurchaseOptions.value = true; |
| | | const res = await purchaseListPage({ |
| | | current: -1, |
| | | size: -1, |
| | | purchaseContractNumber: keyword, |
| | | }); |
| | | const records = res.data?.records || []; |
| | | purchaseOptions.value = records; |
| | | if ( |
| | | form.value.purchaseContractNumber && |
| | | !purchaseOptions.value.find( |
| | | (item) => item.purchaseContractNumber === form.value.purchaseContractNumber |
| | | ) |
| | | ) { |
| | | purchaseOptions.value.push({ |
| | | purchaseContractNumber: form.value.purchaseContractNumber, |
| | | supplierName: form.value.supplierName, |
| | | supplierId: form.value.supplierId, |
| | | }); |
| | | } |
| | | } finally { |
| | | loadingPurchaseOptions.value = false; |
| | | } |
| | | }; |
| | | |
| | | const handlePurchaseChange = (value) => { |
| | | form.value.purchaseContractNumber = value || ''; |
| | | const matched = purchaseOptions.value.find( |
| | | (item) => item.purchaseContractNumber === value |
| | | ); |
| | | if (matched) { |
| | | form.value.supplierName = matched.supplierName || form.value.supplierName; |
| | | form.value.supplierId = matched.supplierId || form.value.supplierId; |
| | | } |
| | | if (!value) { |
| | | productList.value = []; |
| | | return; |
| | | } |
| | | fetchProductsByContract(); |
| | | }; |
| | | const exceedsAddLimit = (product) => { |
| | | const stock = Number(product?.quantityStock ?? 0); |
| | | const waiting = Number(product?.quantity0 ?? 0); |
| | | if (!Number.isFinite(stock) || !Number.isFinite(waiting)) { |
| | | return false; |
| | | } |
| | | return stock > waiting; |
| | | }; |
| | | |
| | | const exceedsEditLimit = (product) => { |
| | | const stock = Number(product?.quantityStock ?? 0); |
| | | const waiting = Number(product?.quantity0 ?? 0); |
| | | const original = Number(product?.originalQuantityStock ?? 0); |
| | | if (!Number.isFinite(stock) || !Number.isFinite(waiting) || !Number.isFinite(original)) { |
| | | return false; |
| | | } |
| | | return stock > waiting + original; |
| | | }; |
| | | const formattedNumber = (row, column, cellValue) => { |
| | | return parseFloat(cellValue).toFixed(2); |
| | | }; |
| | | }); |
| | | const {searchForm} = toRefs(data); |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | page.current = 1 |
| | | getList() |
| | | } |
| | | const paginationChange = (obj) => { |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | const paginationChange = obj => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList() |
| | | } |
| | | getList(); |
| | | }; |
| | | const pageProductChange = obj => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | |
| | | const getList = () => { |
| | | tableLoading.value = true |
| | | getStockInPage({ ...searchForm.value, ...page }).then(res => { |
| | | tableLoading.value = false |
| | | tableData.value = res.data.records |
| | | total.value = res.data.total |
| | | console.log('tableData:', tableData.value) |
| | | }).catch(() => { |
| | | tableLoading.value = false |
| | | tableLoading.value = true; |
| | | const params = {...page}; |
| | | params.timeStr = searchForm.value.timeStr; |
| | | params.productName = searchForm.value.productName; |
| | | getStockInRecordListPage(params) |
| | | .then(res => { |
| | | tableData.value = res.data.records; |
| | | }).finally(() => { |
| | | tableLoading.value = false; |
| | | }) |
| | | } |
| | | }; |
| | | |
| | | |
| | | // è°ç¨selectProductRecordListByPuechaserIdè¿ä¸ªæ¹æ³æ ¹æ®ååæ¥è¯¢å°idï¼åè°ç¨getProductRecordByhetongè¿ä¸ªæ¹æ³æ ¹æ®idæ¥è¯¢å°äº§å订åè®°å½ |
| | | // æ°å¢æ ¹æ®ååå·æ¥è¯¢äº§åè®°å½çæ¹æ³ |
| | | const fetchProductsByContract = async () => |
| | | { |
| | | if (!form.value.purchaseContractNumber) { |
| | | proxy.$modal.msgWarning('è¯·éæ©ååå·') |
| | | return |
| | | } |
| | | try { |
| | | loadingProducts.value = true |
| | | // æ ¹æ®ååæ¥è¯¢äº§åè®°å½ |
| | | const productRes = await selectProductRecordListByPuechaserId({ |
| | | purchaseContractNumber: form.value.purchaseContractNumber |
| | | }); |
| | | console.log('productRes:', productRes) |
| | | if (!productRes.data || productRes.data.length === 0) { |
| | | proxy.$modal.msgWarning('该åå䏿²¡æäº§åè®°å½') |
| | | productList.value = []; |
| | | return |
| | | } |
| | | // å¤çäº§åæ°æ®ï¼æ·»å æ¬æ¬¡å
¥åºæ°éåæ®µ |
| | | productList.value = productRes.data.map(item => ({ |
| | | ...item, |
| | | quantityStock: 0, |
| | | originalQuantityStock: Number(item.quantityStock ?? item.inboundQuantity ?? 0), |
| | | })) |
| | | } catch (error) { |
| | | console.error('æ¥è¯¢äº§åè®°å½å¤±è´¥:', error) |
| | | proxy.$modal.msgError('æ¥è¯¢äº§åè®°å½å¤±è´¥') |
| | | productList.value = []; |
| | | } finally { |
| | | loadingProducts.value = false |
| | | } |
| | | } |
| | | |
| | | |
| | | // æå¼å¼¹æ¡ |
| | | const openForm = async (type, row) => { |
| | | operationType.value = type |
| | | dialogFormVisible.value = true |
| | | selectedRows.value = [] |
| | | await loadPurchaseOptions(); |
| | | |
| | | if (type === 'add') { |
| | | // æ°å¢æ¶åå§å表å |
| | | form.value = { |
| | | id: null, |
| | | purchaseContractNumber: '', |
| | | supplierId: null, |
| | | supplierName: '', |
| | | inboundTime: '', |
| | | inboundBatch: '', |
| | | recorderId: userStore.userId, |
| | | recorderName: userStore.name, |
| | | entryDate: getCurrentDate(), |
| | | remark: '' |
| | | } |
| | | productList.value = [] // æ¸
空产åå表 |
| | | } else { |
| | | form.value = JSON.parse(JSON.stringify(row)) |
| | | try { |
| | | loadingProducts.value = true |
| | | // æ ¹æ®ååå·å 载对åºç产åå表ï¼å设 getProductByContract æ¯å¯ç¨æ¥å£ï¼ |
| | | const res = await selectProductRecordListByPuechaserId({ |
| | | purchaseContractNumber: form.value.purchaseContractNumber, |
| | | id: row.id |
| | | }); |
| | | productList.value = res.data.map(item => ({ |
| | | ...item, |
| | | quantityStock: Number(item.quantityStock ?? item.inboundQuantity ?? row.inboundNum ?? 0), |
| | | originalQuantityStock: Number(item.quantityStock ?? item.inboundQuantity ?? row.inboundNum ?? 0), |
| | | })) |
| | | selectedRows.value = productList.value |
| | | } catch (error) { |
| | | console.error('å 载产å失败:', error) |
| | | proxy.$modal.msgError('å 载产å失败') |
| | | productList.value = [] |
| | | } finally { |
| | | loadingProducts.value = false |
| | | } |
| | | } |
| | | } |
| | | |
| | | const updatePro = async () => { |
| | | // åå¤æäº¤æ°æ® |
| | | // åå¤æäº¤æ°æ® - ä¿®æ¹ä¸ºå端éè¦çæ ¼å¼ |
| | | if (selectedRows.value.length === 0) { |
| | | proxy.$modal.msgWarning('请å
éæ©äº§å'); |
| | | return; |
| | | } |
| | | const target = selectedRows.value[0]; |
| | | const stock = Number(target?.quantityStock ?? 0); |
| | | if (!Number.isFinite(stock) || stock <= 0) { |
| | | proxy.$modal.msgWarning('è¯·å¡«åææçå
¥åºæ°é'); |
| | | return; |
| | | } |
| | | if (exceedsEditLimit(target)) { |
| | | proxy.$modal.msgError('æ¬æ¬¡å
¥åºæ°éä¸è½è¶
è¿åå
¥åºæ°éä¸å¾
å
¥åºæ°éä¹å'); |
| | | return; |
| | | } |
| | | const stockInData = { |
| | | id: selectedRows.value[0].recordId, |
| | | quantityStock: Number(selectedRows.value[0].quantityStock),// ä½¿ç¨æ°æ ¼å¼å彿° |
| | | }; |
| | | await updateStockIn(stockInData) |
| | | proxy.$modal.msgSuccess('ä¿®æ¹å
¥åºæå') |
| | | closeDia() |
| | | getList() // å·æ°å表 |
| | | } |
| | | |
| | | // æäº¤è¡¨å |
| | | const submitForm = async () => { |
| | | // éªè¯è³å°éæ©äºä¸ä¸ªäº§å |
| | | if (selectedRows.value.length === 0) { |
| | | proxy.$modal.msgWarning('请å
éæ©éè´ååå¹¶éæ©äº§å') |
| | | return |
| | | } |
| | | if(operationType.value !== 'add'){ |
| | | await updatePro() |
| | | return |
| | | } |
| | | try { |
| | | await proxy.$refs.formRef.validate() |
| | | // éªè¯å
¥åºæ°é |
| | | const invalidProducts = selectedRows.value.filter((product) => { |
| | | const stock = Number(product?.quantityStock ?? 0); |
| | | if (!Number.isFinite(stock) || stock <= 0) { |
| | | return true; |
| | | } |
| | | return exceedsAddLimit(product); |
| | | }) |
| | | |
| | | if (invalidProducts.length > 0) { |
| | | proxy.$modal.msgError('æ¬æ¬¡å
¥åºæ°éé大äº0ï¼ä¸ä¸è½è¶
è¿å¾
å
¥åºæ°é') |
| | | return |
| | | } |
| | | |
| | | // åå¤æäº¤æ°æ® - ä¿®æ¹ä¸ºå端éè¦çæ ¼å¼ |
| | | const stockInData = { |
| | | // å
¥åºååºæ¬ä¿¡æ¯ |
| | | ...form.value, |
| | | inboundTime: formatDateTime(form.value.inboundTime), |
| | | nickName: userStore.nickName, |
| | | details: selectedRows.value.map(product => ({ |
| | | id: product.id, |
| | | // id: product.salesLedgerProductId, |
| | | inboundQuantity: Number(product.quantityStock) |
| | | })), |
| | | }; |
| | | // è°ç¨API |
| | | loading.value = true |
| | | await addSutockIn(stockInData) |
| | | |
| | | proxy.$modal.msgSuccess('æ°å¢å
¥åºæå') |
| | | closeDia() |
| | | getList() // å·æ°å表 |
| | | |
| | | } catch (error) { |
| | | console.error('æäº¤å¤±è´¥:', error) |
| | | if (!error.errors) { |
| | | proxy.$modal.msgError('æä½å¤±è´¥ï¼è¯·éè¯') |
| | | } |
| | | } finally { |
| | | loading.value = false |
| | | } |
| | | } |
| | | |
| | | // å
³éå¼¹æ¡ |
| | | const closeDia = () => { |
| | | proxy.$refs.formRef.resetFields() |
| | | dialogFormVisible.value = false |
| | | |
| | | } |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = (selection) => { |
| | | // è¿æ»¤æåæ°æ® |
| | | selectedRows.value = selection.filter(item => item.id); |
| | | } |
| | | const handleSelectionChange = selection => { |
| | | selectedRows.value = selection.filter(item => item.id); |
| | | }; |
| | | |
| | | const expandedRowKeys = ref([]) |
| | | const expandedRowKeys = ref([]); |
| | | |
| | | // 主表åè®¡æ¹æ³ |
| | | const summarizeMainTable = (param) => { |
| | | return proxy.summarizeTable(param, ['contractAmount', 'taxInclusiveTotalPrice', 'taxExclusiveTotalPrice']); |
| | | }; |
| | | const summarizeMainTable = param => { |
| | | return proxy.summarizeTable(param, [ |
| | | "contractAmount", |
| | | "taxInclusiveTotalPrice", |
| | | "taxExclusiveTotalPrice", |
| | | ]); |
| | | }; |
| | | |
| | | // å¯¼åº |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm( |
| | | 'æ¯å¦ç¡®è®¤å¯¼åºï¼', |
| | | '导åº', { |
| | | confirmButtonText: '确认', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning', |
| | | } |
| | | ).then(() => { |
| | | proxy.download("/stockin/export", {}, 'å
¥åºå°è´¦.xlsx') |
| | | }).catch(() => { |
| | | proxy.$modal.msg("已忶") |
| | | }) |
| | | } |
| | | // å é¤ |
| | | const handleDelete = () => { |
| | | let ids = [] |
| | | if (selectedRows.value.length > 0) { |
| | | // æ£æ¥æ¯å¦æä»äººç»´æ¤çæ°æ® |
| | | const unauthorizedData = selectedRows.value.filter(item => item.createUser !== userStore.id); |
| | | if (unauthorizedData.length > 0) { |
| | | proxy.$modal.msgWarning("ä¸å¯å é¤ä»äººç»´æ¤çæ°æ®"); |
| | | return; |
| | | } |
| | | ids = selectedRows.value.map(item => item.id); |
| | | } else { |
| | | proxy.$modal.msgWarning('è¯·éæ©æ°æ®') |
| | | return |
| | | } |
| | | ElMessageBox.confirm( |
| | | 'éä¸çå
容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼', |
| | | '导åº', { |
| | | confirmButtonText: '确认', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning', |
| | | } |
| | | ).then(() => { |
| | | delStockIn({ids:ids}).then(res => { |
| | | proxy.$modal.msgSuccess("å 餿å") |
| | | getList() |
| | | }) |
| | | }).catch(() => { |
| | | proxy.$modal.msg("已忶") |
| | | }) |
| | | } |
| | | |
| | | // è·åå½åæ¥æå¹¶æ ¼å¼å为 YYYY-MM-DD |
| | | // ä¿®æ¹ä¸ºæ´éç¨çæ¥ææ¶é´æ ¼å¼å彿° |
| | | function formatDateTime(date = new Date(), includeTime = true) { |
| | | const d = new Date(date); |
| | | const year = d.getFullYear(); |
| | | const month = String(d.getMonth() + 1).padStart(2, '0'); |
| | | const day = String(d.getDate()).padStart(2, '0'); |
| | | |
| | | if (!includeTime) { |
| | | return `${year}-${month}-${day}`; // ä¿æåæ getCurrentDate åè½ |
| | | } |
| | | |
| | | // æ°å¢æ¶é´é¨åæ ¼å¼å |
| | | const hours = String(d.getHours()).padStart(2, '0'); |
| | | const minutes = String(d.getMinutes()).padStart(2, '0'); |
| | | const seconds = String(d.getSeconds()).padStart(2, '0'); |
| | | |
| | | return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; |
| | | } |
| | | |
| | | onMounted(() => { |
| | | getList() |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | // æ ¹æ®ä¸åç tab ç±»åè°ç¨ä¸åçå¯¼åºæ¥å£ |
| | | let exportUrl = "/stockin/export"; |
| | | if (activeTab.value === "production") { |
| | | exportUrl = "/stockin/exportOne"; |
| | | } |
| | | proxy.download(exportUrl, {}, "å
¥åºå°è´¦.xlsx"); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | |
| | | // å é¤ |
| | | const handleDelete = () => { |
| | | if (selectedRows.value.length === 0) { |
| | | proxy.$modal.msgWarning("è¯·éæ©æ°æ®"); |
| | | return; |
| | | } |
| | | const ids = selectedRows.value.map(item => item.id); |
| | | |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼", "å é¤", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | batchDeleteStockInRecords(ids) |
| | | .then(() => { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | getList(); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msgError("å é¤å¤±è´¥"); |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"></style> |
| | | |
| | | |
| | | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div> |
| | | <el-dialog |
| | | v-model="isShow" |
| | | title="æ°å¢åºå" |
| | | width="800" |
| | | @close="closeModal" |
| | | > |
| | | <el-form label-width="140px" :model="formState" label-position="top" ref="formRef"> |
| | | <el-form-item |
| | | label="产ååç§°" |
| | | prop="productModelId" |
| | | :rules="[ |
| | | { |
| | | required: true, |
| | | message: 'è¯·éæ©äº§å', |
| | | trigger: 'change', |
| | | } |
| | | ]" |
| | | > |
| | | <el-button type="primary" @click="showProductSelectDialog = true"> |
| | | {{ formState.productName ? formState.productName : 'éæ©äº§å' }} |
| | | </el-button> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | label="è§æ ¼" |
| | | prop="productModelName" |
| | | > |
| | | <el-input v-model="formState.productModelName" disabled /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | label="åä½" |
| | | prop="unit" |
| | | > |
| | | <el-input v-model="formState.unit" disabled /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | label="æ°é" |
| | | prop="qualitity" |
| | | > |
| | | <el-input-number v-model="formState.qualitity" :step="1" :min="0" style="width: 100%" /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="夿³¨" prop="remark"> |
| | | <el-input v-model="formState.remark" type="textarea" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | |
| | | <!-- 产åéæ©å¼¹çª --> |
| | | <ProductSelectDialog |
| | | v-model="showProductSelectDialog" |
| | | @confirm="handleProductSelect" |
| | | single |
| | | /> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="handleSubmit">确认</el-button> |
| | | <el-button @click="closeModal">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {ref, computed, getCurrentInstance} from "vue"; |
| | | import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue"; |
| | | import {createStockInventory} from "@/api/inventoryManagement/stockInventory.js"; |
| | | |
| | | const props = defineProps({ |
| | | visible: { |
| | | type: Boolean, |
| | | required: true, |
| | | }, |
| | | }); |
| | | |
| | | const emit = defineEmits(['update:visible', 'completed']); |
| | | |
| | | // ååºå¼æ°æ®ï¼æ¿ä»£é项å¼ç dataï¼ |
| | | const formState = ref({ |
| | | productId: undefined, |
| | | productModelId: undefined, |
| | | productName: "", |
| | | productModelName: "", |
| | | unit: "", |
| | | qualitity: 0, |
| | | remark: '', |
| | | }); |
| | | |
| | | const isShow = computed({ |
| | | get() { |
| | | return props.visible; |
| | | }, |
| | | set(val) { |
| | | emit('update:visible', val); |
| | | }, |
| | | }); |
| | | |
| | | const showProductSelectDialog = ref(false); |
| | | |
| | | let { proxy } = getCurrentInstance() |
| | | |
| | | const closeModal = () => { |
| | | // éç½®è¡¨åæ°æ® |
| | | formState.value = { |
| | | productId: undefined, |
| | | productModelId: undefined, |
| | | productName: "", |
| | | productModelName: "", |
| | | description: '', |
| | | }; |
| | | isShow.value = false; |
| | | }; |
| | | |
| | | // 产åéæ©å¤ç |
| | | const handleProductSelect = async (products) => { |
| | | if (products && products.length > 0) { |
| | | const product = products[0]; |
| | | console.log(product) |
| | | formState.value.productId = product.productId; |
| | | formState.value.productName = product.productName; |
| | | formState.value.productModelName = product.model; |
| | | formState.value.productModelId = product.id; |
| | | formState.value.unit = product.unit; |
| | | showProductSelectDialog.value = false; |
| | | // 触å表åéªè¯æ´æ° |
| | | proxy.$refs["formRef"]?.validateField('productModelId'); |
| | | } |
| | | }; |
| | | |
| | | const handleSubmit = () => { |
| | | proxy.$refs["formRef"].validate(valid => { |
| | | if (valid) { |
| | | // éªè¯æ¯å¦éæ©äºäº§ååè§æ ¼ |
| | | if (!formState.value.productModelId) { |
| | | proxy.$modal.msgError("è¯·éæ©äº§å"); |
| | | return; |
| | | } |
| | | if (!formState.value.productModelId) { |
| | | proxy.$modal.msgError("è¯·éæ©è§æ ¼"); |
| | | return; |
| | | } |
| | | createStockInventory(formState.value).then(res => { |
| | | // å
³éæ¨¡ææ¡ |
| | | isShow.value = false; |
| | | // åç¥ç¶ç»ä»¶å·²å®æ |
| | | emit('completed'); |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | }) |
| | | } |
| | | }) |
| | | }; |
| | | |
| | | |
| | | defineExpose({ |
| | | closeModal, |
| | | handleSubmit, |
| | | isShow, |
| | | }); |
| | | </script> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div> |
| | | <el-dialog |
| | | v-model="isShow" |
| | | title="é¢ç¨" |
| | | width="800" |
| | | @close="closeModal" |
| | | > |
| | | <el-form label-width="140px" :model="formState" label-position="top" ref="formRef"> |
| | | <el-form-item |
| | | label="产ååç§°" |
| | | prop="productModelId" |
| | | :rules="[ |
| | | { |
| | | required: true, |
| | | message: 'è¯·éæ©äº§å', |
| | | trigger: 'change', |
| | | } |
| | | ]" |
| | | > |
| | | <el-button type="primary" @click="showProductSelectDialog = true" disabled> |
| | | {{ formState.productName ? formState.productName : 'éæ©äº§å' }} |
| | | </el-button> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | label="è§æ ¼" |
| | | prop="productModelName" |
| | | > |
| | | <el-input v-model="formState.model" disabled /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | label="åä½" |
| | | prop="unit" |
| | | > |
| | | <el-input v-model="formState.unit" disabled /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item |
| | | label="æ°é" |
| | | prop="qualitity" |
| | | > |
| | | <el-input-number v-model="formState.qualitity" :step="1" :min="1" :max="maxQuality" style="width: 100%" /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="夿³¨" prop="remark"> |
| | | <el-input v-model="formState.remark" type="textarea" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | |
| | | <!-- 产åéæ©å¼¹çª --> |
| | | <ProductSelectDialog |
| | | v-model="showProductSelectDialog" |
| | | @confirm="handleProductSelect" |
| | | single |
| | | /> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="handleSubmit">确认</el-button> |
| | | <el-button @click="closeModal">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {ref, computed, getCurrentInstance} from "vue"; |
| | | import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue"; |
| | | import {subtractStockInventory} from "@/api/inventoryManagement/stockInventory.js"; |
| | | |
| | | const props = defineProps({ |
| | | visible: { |
| | | type: Boolean, |
| | | required: true, |
| | | }, |
| | | record: { |
| | | type: Object, |
| | | default: () => {}, |
| | | } |
| | | }); |
| | | |
| | | const emit = defineEmits(['update:visible', 'completed']); |
| | | |
| | | onMounted(() => { |
| | | initFormData() |
| | | }) |
| | | |
| | | const maxQuality = computed(() => { |
| | | return props.record.qualitity ? props.record.qualitity : 0; |
| | | }) |
| | | |
| | | const initFormData = () => { |
| | | if (props.record) { |
| | | formState.value = { |
| | | ...props.record, |
| | | } |
| | | } |
| | | } |
| | | |
| | | // ååºå¼æ°æ®ï¼æ¿ä»£é项å¼ç dataï¼ |
| | | const formState = ref({ |
| | | productId: undefined, |
| | | productModelId: undefined, |
| | | productName: "", |
| | | model: "", |
| | | unit: "", |
| | | qualitity: 0, |
| | | remark: '', |
| | | }); |
| | | |
| | | const isShow = computed({ |
| | | get() { |
| | | return props.visible; |
| | | }, |
| | | set(val) { |
| | | emit('update:visible', val); |
| | | }, |
| | | }); |
| | | |
| | | const showProductSelectDialog = ref(false); |
| | | |
| | | let { proxy } = getCurrentInstance() |
| | | |
| | | const closeModal = () => { |
| | | // éç½®è¡¨åæ°æ® |
| | | formState.value = { |
| | | productId: undefined, |
| | | productModelId: undefined, |
| | | productName: "", |
| | | productModelName: "", |
| | | description: '', |
| | | }; |
| | | isShow.value = false; |
| | | }; |
| | | |
| | | // 产åéæ©å¤ç |
| | | const handleProductSelect = async (products) => { |
| | | if (products && products.length > 0) { |
| | | const product = products[0]; |
| | | console.log(product) |
| | | formState.value.productId = product.productId; |
| | | formState.value.productName = product.productName; |
| | | formState.value.productModelName = product.model; |
| | | formState.value.productModelId = product.id; |
| | | formState.value.unit = product.unit; |
| | | showProductSelectDialog.value = false; |
| | | // 触å表åéªè¯æ´æ° |
| | | proxy.$refs["formRef"]?.validateField('productModelId'); |
| | | } |
| | | }; |
| | | |
| | | const handleSubmit = () => { |
| | | proxy.$refs["formRef"].validate(valid => { |
| | | if (valid) { |
| | | // éªè¯æ¯å¦éæ©äºäº§ååè§æ ¼ |
| | | if (!formState.value.productModelId) { |
| | | proxy.$modal.msgError("è¯·éæ©äº§å"); |
| | | return; |
| | | } |
| | | if (!formState.value.productModelId) { |
| | | proxy.$modal.msgError("è¯·éæ©è§æ ¼"); |
| | | return; |
| | | } |
| | | subtractStockInventory(formState.value).then(res => { |
| | | // å
³éæ¨¡ææ¡ |
| | | isShow.value = false; |
| | | // åç¥ç¶ç»ä»¶å·²å®æ |
| | | emit('completed'); |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | }) |
| | | } |
| | | }) |
| | | }; |
| | | |
| | | |
| | | defineExpose({ |
| | | closeModal, |
| | | handleSubmit, |
| | | isShow, |
| | | }); |
| | | </script> |
| | |
| | | <div class="app-container"> |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title">ä¾åºååç§°ï¼</span> |
| | | <el-input v-model="searchForm.supplierName" style="width: 240px" placeholder="请è¾å
¥" @change="handleQuery" |
| | | clearable prefix-icon="Search" /> |
| | | <span class="search_title ml10">å
¥åºæ¥æï¼</span> |
| | | <el-date-picker |
| | | v-model="searchForm.timeStr" |
| | | type="date" |
| | | placeholder="è¯·éæ©æ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | clearable |
| | | @change="handleQuery" |
| | | /> |
| | | <span class="search_title ml10">产å大类ï¼</span> |
| | | <el-input v-model="searchForm.productName" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥" |
| | | clearable/> |
| | | <el-button type="primary" @click="handleQuery" style="margin-left: 10px">æç´¢</el-button> |
| | | </div> |
| | | <div> |
| | | <!-- <el-button type="primary" @click="openForm('add')">æ°å¢</el-button> --> |
| | | <el-button type="primary" @click="isShowNewModal = true">æ°å¢åºå</el-button> |
| | | <el-button @click="handleOut">导åº</el-button> |
| | | <el-button type="danger" plain @click="handleDelete">å é¤</el-button> |
| | | </div> |
| | | </div> |
| | | <div class="table_list"> |
| | | <el-table :data="tableData" border v-loading="tableLoading" @selection-change="handleSelectionChange" |
| | | :expand-row-keys="expandedRowKeys" :row-key="row => row.id" show-summary style="width: 100%" |
| | | :row-class-name="tableRowClassName" |
| | | :summary-method="summarizeMainTable" height="calc(100vh - 18.5em)"> |
| | | :expand-row-keys="expandedRowKeys" :row-key="row => row.id" style="width: 100%" |
| | | :row-class-name="tableRowClassName" height="calc(100vh - 18.5em)"> |
| | | <el-table-column align="center" type="selection" width="55" /> |
| | | <el-table-column align="center" label="åºå·" type="index" width="60" /> |
| | | <el-table-column label="å
¥åºæ¥æ" prop="createTime" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="ä¾åºååç§°" prop="supplierName" width="240" show-overflow-tooltip /> |
| | | <el-table-column label="产å大类" prop="productCategory" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="è§æ ¼åå·" prop="specificationModel" width="200" show-overflow-tooltip /> |
| | | <el-table-column label="åä½" prop="unit" width="80" show-overflow-tooltip /> |
| | | <el-table-column label="åºåæ°é" prop="inboundNum0" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="åºåé¢è¦æ°é" prop="warnNum" width="130" show-overflow-tooltip /> |
| | | <el-table-column label="å«ç¨åä»·" prop="taxInclusiveUnitPrice" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="å«ç¨æ»ä»·" prop="taxInclusiveTotalPrice" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="ç¨ç(%)" prop="taxRate" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="ä¸å«ç¨æ»ä»·" prop="taxExclusiveTotalPrice" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="å
¥åºäºº" prop="createBy" width="80" show-overflow-tooltip /> |
| | | <el-table-column label="å
¥åºæ¥æ" prop="createTime" show-overflow-tooltip /> |
| | | <el-table-column label="产å大类" prop="productName" show-overflow-tooltip /> |
| | | <el-table-column label="è§æ ¼åå·" prop="model" show-overflow-tooltip /> |
| | | <el-table-column label="åä½" prop="unit" show-overflow-tooltip /> |
| | | <el-table-column label="åºåæ°é" prop="qualitity" show-overflow-tooltip /> |
| | | <el-table-column label="åºåé¢è¦æ°é" prop="warnNum" show-overflow-tooltip /> |
| | | <el-table-column label="æè¿æ´æ°æ¶é´" prop="updateTime" show-overflow-tooltip /> |
| | | <el-table-column fixed="right" label="æä½" min-width="60" align="center"> |
| | | <template #default="scope"> |
| | | <el-button link type="primary" size="small" @click="openForm('edit', scope.row);">ç¼è¾</el-button> |
| | | <el-button link type="primary" size="small" @click="showSubtractModal(scope.row)" :disabled="scope.row.qualitity === 0">é¢ç¨</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <pagination v-show="total > 0" :total="total" layout="total, sizes, prev, pager, next, jumper" |
| | | :page="page.current" :limit="page.size" @pagination="paginationChange" /> |
| | | </div> |
| | | <el-dialog v-model="dialogFormVisible" :title="operationType === 'add' ? 'æ°å¢åºå' : 'ç¼è¾åºå'" width="70%" |
| | | @close="closeDia"> |
| | | <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef"> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ä¾åºååç§°ï¼" prop="supplierName"> |
| | | <el-input disabled v-model="form.supplierName" placeholder="请è¾å
¥" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="产å大类ï¼" prop="productId"> |
| | | <el-select disabled v-model="form.productCategory" placeholder="è¯·éæ©" clearable filterable> |
| | | <el-option v-for="item in productList" :key="item.id" :label="item.productName" |
| | | :value="item.productName" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="è§æ ¼åå·ï¼" prop="productManageId"> |
| | | <el-select disabled v-model="form.specificationModel" placeholder="请å
éæ©äº§å大类" clearable filterable :disabled="!form.productCategory"> |
| | | <el-option v-for="item in productModelList" :key="item.id" :label="item.model" |
| | | :value="item.id" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="åä½ï¼" prop="customerId"> |
| | | <el-input disabled v-model="form.unit" placeholder="请è¾å
¥" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="åºåæ¶é´ï¼" prop="projectName"> |
| | | <el-date-picker style="width: 100%" v-model="form.updateTime" value-format="YYYY-MM-DD" format="YYYY-MM-DD" |
| | | type="date" placeholder="è¯·éæ©" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å
¥åºæ¶é´ï¼" prop="projectName"> |
| | | <el-date-picker style="width: 100%" v-model="form.createTime" value-format="YYYY-MM-DD" format="YYYY-MM-DD" |
| | | type="date" placeholder="è¯·éæ©" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <new-stock-inventory v-if="isShowNewModal" |
| | | v-model:visible="isShowNewModal" |
| | | @completed="handleQuery" /> |
| | | |
| | | <el-col :span="12"> |
| | | <el-form-item label="å«ç¨åä»·ï¼" prop="customerId"> |
| | | <el-input disabled v-model="form.taxInclusiveUnitPrice" placeholder="请è¾å
¥" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å«ç¨æ»ä»·ï¼" prop="customerContractNo"> |
| | | <el-input disabled v-model="form.taxInclusiveTotalPrice" placeholder="请è¾å
¥" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç¨çï¼" prop="customerId"> |
| | | <el-input disabled v-model="form.taxRate" placeholder="请è¾å
¥" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ä¸å«ç¨æ»ä»·ï¼" prop="entryDate"> |
| | | <el-input disabled v-model="form.taxExclusiveTotalPrice" placeholder="请è¾å
¥" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="åºåºäººï¼" prop="entryPerson"> |
| | | <el-select v-model="form.createUser" placeholder="è¯·éæ©" clearable> |
| | | <el-option v-for="item in userList" :key="item.userId" :label="item.nickName" :value="item.userId" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <!-- <el-col :span="12">--> |
| | | <!-- <el-form-item label="åºåé¢è¦æ°éï¼" prop="warnNum">--> |
| | | <!-- <el-input v-model="form.warnNum" placeholder="请è¾å
¥æä½åºå" clearable />--> |
| | | <!-- </el-form-item>--> |
| | | <!-- </el-col>--> |
| | | </el-row> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="submitForm">确认</el-button> |
| | | <el-button @click="closeDia">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | <subtract-stock-inventory v-if="isShowSubtractModal" |
| | | v-model:visible="isShowSubtractModal" |
| | | :record="record" |
| | | @completed="handleQuery" /> |
| | | </div> |
| | | </template> |
| | | |
| | |
| | | import pagination from '@/components/PIMTable/Pagination.vue' |
| | | import { ref, reactive, toRefs, onMounted, getCurrentInstance } from 'vue' |
| | | import { ElMessageBox } from "element-plus"; |
| | | import useUserStore from '@/store/modules/user' |
| | | import { userListNoPageByTenantId } from "@/api/system/user.js"; |
| | | import { productTreeList,modelList } from "@/api/basicData/product.js" |
| | | import { getCurrentDate } from "@/utils/index.js"; |
| | | import { |
| | | getStockManagePage, |
| | | delStockManage, |
| | | } from "@/api/inventoryManagement/stockManage.js"; |
| | | import { |
| | | updateManagement,updateStockIn |
| | | } from "@/api/inventoryManagement/stockIn.js"; |
| | | import { getStockInventoryListPage } from "@/api/inventoryManagement/stockInventory.js"; |
| | | const NewStockInventory = defineAsyncComponent(() => import("@/views/inventoryManagement/stockManagement/New.vue")); |
| | | const SubtractStockInventory = defineAsyncComponent(() => import("@/views/inventoryManagement/stockManagement/Subtract.vue")); |
| | | |
| | | |
| | | |
| | | const userStore = useUserStore() |
| | | const { proxy } = getCurrentInstance() |
| | | const tableData = ref([]) |
| | | const productData = ref([]) |
| | | const selectedRows = ref([]) |
| | | const userList = ref([]) |
| | | const productList = ref([]) |
| | | const productModelList = ref([]) |
| | | // const customerOption = ref([]) |
| | | const record = ref({}) |
| | | const tableLoading = ref(false) |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | }) |
| | | const total = ref(0) |
| | | const fileList = ref([]) |
| | | const loading = ref(false); |
| | | // ç¨æ·ä¿¡æ¯è¡¨åå¼¹æ¡æ°æ® |
| | | const operationType = ref('') |
| | | const dialogFormVisible = ref(false) |
| | | // æ¯å¦æ¾ç¤ºæ°å¢å¼¹æ¡ |
| | | const isShowNewModal = ref(false) |
| | | // æ¯å¦æ¾ç¤ºé¢ç¨å¼¹æ¡ |
| | | const isShowSubtractModal = ref(false) |
| | | const data = reactive({ |
| | | searchForm: { |
| | | supplierName: '', |
| | | timeStr: '', |
| | | }, |
| | | form: { |
| | | supplierId: null, |
| | | supplierName: '', |
| | | productId: null, |
| | | productName: '', |
| | | userId: userStore.userId, |
| | | nickName: '', |
| | | productModelId: null, |
| | | model: '', |
| | | unit: '', |
| | | productrecordId: null, |
| | | taxInclusiveUnitPrice: '', |
| | | taxInclusiveTotalPrice: '', |
| | | taxRate: '', |
| | | taxExclusiveTotalPrice: '', |
| | | inboundTime: '', |
| | | inboundBatch: '', |
| | | stockQuantity: '', |
| | | boundTime: '', |
| | | warnNum: '', // æ°å¢æä½åºååæ®µ |
| | | salesLedgerProductId: null, |
| | | }, |
| | | rules: { |
| | | supplierName: [{ required: true, message: '请è¾å
¥ä¾åºååç§°', trigger: 'blur' }], |
| | | productCategory: [{ required: true, message: 'è¯·éæ©äº§å大类', trigger: 'change' }], |
| | | specificationModel: [{ required: true, message: '请è¾å
¥è§æ ¼åå·', trigger: 'blur' }], |
| | | unit: [{ required: true, message: '请è¾å
¥åä½', trigger: 'blur' }], |
| | | stockQuantity: [{ required: true, message: '请è¾å
¥åºåºæ°é', trigger: 'blur' }], |
| | | taxInclusiveUnitPrice: [{ required: true, message: '请è¾å
¥å«ç¨åä»·', trigger: 'blur' }], |
| | | taxInclusiveTotalPrice: [{ required: true, message: '请è¾å
¥å«ç¨æ»ä»·', trigger: 'blur' }], |
| | | taxRate: [{ required: true, message: '请è¾å
¥ç¨ç', trigger: 'blur' }], |
| | | taxExclusiveTotalPrice: [{ required: true, message: '请è¾å
¥ä¸å«ç¨æ»ä»·', trigger: 'blur' }], |
| | | boundTime: [{ required: true, message: 'è¯·éæ©åºåæ¶é´', trigger: 'change' }], |
| | | inboundTime: [{ required: true, message: 'è¯·éæ©å
¥åºæ¶é´', trigger: 'change' }], |
| | | inboundPerson: [{ required: true, message: 'è¯·éæ©åºåºäºº', trigger: 'change' }], |
| | | warnNum: [{ required: true, message: '请è¾å
¥æä½åºå', trigger: 'blur' }], |
| | | } |
| | | }) |
| | | const { searchForm, form, rules } = toRefs(data) |
| | | const { searchForm } = toRefs(data) |
| | | |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | |
| | | } |
| | | const getList = () => { |
| | | tableLoading.value = true |
| | | getStockManagePage({ ...searchForm.value, ...page }).then(res => { |
| | | getStockInventoryListPage({ ...searchForm.value, ...page }).then(res => { |
| | | tableLoading.value = false |
| | | tableData.value = res.data.records |
| | | total.value = res.data.total |
| | |
| | | }) |
| | | } |
| | | |
| | | // ç¹å»é¢ç¨ |
| | | const showSubtractModal = (row) => { |
| | | record.value = row |
| | | isShowSubtractModal.value = true |
| | | } |
| | | |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = (selection) => { |
| | | |
| | | // è¿æ»¤æåæ°æ® |
| | | selectedRows.value = selection.filter(item => item.id); |
| | | console.log('selection', selectedRows.value) |
| | | } |
| | | const expandedRowKeys = ref([]) |
| | | |
| | | // 主表åè®¡æ¹æ³ |
| | | const summarizeMainTable = (param) => { |
| | | return proxy.summarizeTable(param, ['contractAmount', 'taxInclusiveTotalPrice', 'taxExclusiveTotalPrice']); |
| | | }; |
| | | |
| | | // è¡¨æ ¼è¡ç±»å |
| | | const tableRowClassName = ({ row }) => { |
| | |
| | | } |
| | | return stock < warn ? 'row-low-stock' : ''; |
| | | }; |
| | | |
| | | // æå¼å¼¹æ¡ |
| | | const openForm = async (type, row) => { |
| | | operationType.value = type |
| | | form.value = {} |
| | | productData.value = [] |
| | | let userLists = await userListNoPageByTenantId() |
| | | userList.value = userLists.data |
| | | if (type === 'edit') { |
| | | form.value = { ...row } |
| | | productTreeList().then(res =>{ |
| | | productList.value = res |
| | | productList.value.forEach(i =>{ |
| | | if (i.label === row.productCategory) { |
| | | modelList({ id: i.id }).then((res) => { |
| | | productModelList.value = res; |
| | | }); |
| | | } |
| | | }) |
| | | }) |
| | | } |
| | | form.value.entryDate = getCurrentDate() // 设置é»è®¤å½å
¥æ¥æä¸ºå½åæ¥æ |
| | | dialogFormVisible.value = true |
| | | } |
| | | |
| | | // æäº¤è¡¨å |
| | | const submitForm = () => { |
| | | console.log(form.value) |
| | | proxy.$refs["formRef"].validate(valid => { |
| | | if (valid) { |
| | | |
| | | updateManagement(form.value).then(res => { |
| | | proxy.$modal.msgSuccess("æäº¤æå") |
| | | closeDia() |
| | | getList() |
| | | // æäº¤åæ£æ¥åºåå¹¶å°è¯å建请è´å |
| | | // checkStockAndCreatePurchase(); |
| | | }) |
| | | } |
| | | }) |
| | | } |
| | | // æ£æ¥åºåå¹¶å建请è´å |
| | | // const checkStockAndCreatePurchase = async () => { |
| | | // const stockList = tableData.value; |
| | | // // handList() |
| | | // for (const item of stockList) { |
| | | // if (item.inboundNum0 < item.warnNum) { |
| | | // try { |
| | | // const stockInData = { |
| | | // id: item.id, |
| | | // quantityStock: item.warnNum + item.totalInboundNum,// ä½¿ç¨æ°æ ¼å¼å彿° |
| | | // }; |
| | | // loading.value = true |
| | | // await updateStockIn(stockInData) |
| | | // proxy.$modal.msgSuccess(`产å ${item.productCategory} ä¿®æ¹å
¥åºæå`) |
| | | // loading.value = false |
| | | // } catch (error) { |
| | | // proxy.$modal.msgError(`产å ${item.productCategory} çæè¯·è´å失败ï¼è¯·æå¨å¤ç`); |
| | | // |
| | | // } |
| | | // } |
| | | // } |
| | | // }; |
| | | // å
³éå¼¹æ¡ |
| | | const closeDia = () => { |
| | | proxy.resetForm("formRef") |
| | | dialogFormVisible.value = false |
| | | } |
| | | |
| | | // å¯¼åº |
| | | const handleOut = () => { |
| | |
| | | proxy.$modal.msg("已忶") |
| | | }) |
| | | } |
| | | // å é¤ |
| | | const handleDelete = () => { |
| | | let ids = [] |
| | | if (selectedRows.value.length > 0) { |
| | | // æ£æ¥æ¯å¦æä»äººç»´æ¤çæ°æ® |
| | | const unauthorizedData = selectedRows.value.filter(item => item.createUser !== userStore.id); |
| | | if (unauthorizedData.length > 0) { |
| | | proxy.$modal.msgWarning("ä¸å¯å é¤ä»äººç»´æ¤çæ°æ®"); |
| | | return; |
| | | } |
| | | ids = selectedRows.value.map(item => item.id); |
| | | } else { |
| | | proxy.$modal.msgWarning('è¯·éæ©æ°æ®') |
| | | return |
| | | } |
| | | ElMessageBox.confirm( |
| | | 'éä¸çå
容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼', |
| | | '导åº', { |
| | | confirmButtonText: '确认', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning', |
| | | } |
| | | ).then(() => { |
| | | delStockManage({ids:ids}).then(res => { |
| | | proxy.$modal.msgSuccess("å 餿å") |
| | | getList() |
| | | }) |
| | | }).catch(() => { |
| | | proxy.$modal.msg("已忶") |
| | | }) |
| | | } |
| | | |
| | | onMounted(() => { |
| | | getList() |
| | | // checkStockAndCreatePurchase(); |
| | | // æ¯å°æ¶æ£æ¥ä¸æ¬¡åºå |
| | | // const intervalId = setInterval(checkStockAndCreatePurchase, 60 * 60 * 1000); |
| | | |
| | | // onUnmounted(() => { |
| | | // // ç»ä»¶å¸è½½æ¶æ¸
é¤å®æ¶å¨ |
| | | // clearInterval(intervalId); |
| | | // }); |
| | | }) |
| | | </script> |
| | | |
| | |
| | | import useFormData from "@/hooks/useFormData"; |
| | | import {ref,onMounted} from "vue"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import {getStaffOnJob} from "@/api/personnelManagement/onboarding.js"; |
| | | import {deepCopySameProperties} from '@/utils/util' |
| | | const userStore = useUserStore(); |
| | | import { |
| | | getDept |
| | | } from "@/api/collaborativeApproval/approvalProcess.js"; |
| | | import {staffOnJobListPage} from "@/api/personnelManagement/staffOnJob.js"; |
| | | const { proxy } = getCurrentInstance(); |
| | | |
| | | |
| | |
| | | issueDate: undefined, |
| | | }); |
| | | const getPersonList = () => { |
| | | getStaffOnJob().then(res => { |
| | | personList.value = res.data |
| | | staffOnJobListPage({ |
| | | current: -1, |
| | | size: -1, |
| | | staffState: 1 |
| | | }).then(res => { |
| | | personList.value = res.data.records |
| | | }) |
| | | }; |
| | | const loadForm = (data) => { |
| | |
| | | size="large"
|
| | | auto-complete="off"
|
| | | placeholder="è´¦å·"
|
| | | @input="getUserLoginFacotryList"
|
| | | >
|
| | | <template #prefix><el-icon><User /></el-icon></template>
|
| | | </el-input>
|
| | |
| | | >
|
| | | <template #prefix><svg-icon icon-class="password" class="el-input__icon input-icon" /></template>
|
| | | </el-input>
|
| | | </el-form-item>
|
| | | <el-form-item prop="currentFatoryId">
|
| | | <el-select v-model="loginForm.currentFatoryId" placeholder="è¯·éæ©å
¬å¸" >
|
| | | <el-option v-for="item in factoryList" :key="item.deptId" :label="item.deptName" :value="item.deptId" />
|
| | | </el-select>
|
| | | </el-form-item>
|
| | | <!-- <el-form-item prop="code" v-if="captchaEnabled">-->
|
| | | <!-- <el-input-->
|
| | |
| | | import Cookies from "js-cookie"
|
| | | import { encrypt, decrypt } from "@/utils/jsencrypt"
|
| | | import useUserStore from '@/store/modules/user'
|
| | | import {userLoginFacotryList} from "@/api/system/user.js"
|
| | |
|
| | | const title = import.meta.env.VITE_APP_TITLE
|
| | | const userStore = useUserStore()
|
| | |
| | | username: "",
|
| | | password: "",
|
| | | rememberMe: false,
|
| | | currentFatoryId:'',
|
| | | })
|
| | |
|
| | | const loginRules = {
|
| | |
| | | // 注åå¼å
³
|
| | | const register = ref(false)
|
| | | const redirect = ref(undefined)
|
| | |
|
| | | const factoryList = ref([])
|
| | | const currentFatoryId = ref('')
|
| | |
|
| | | watch(route, (newRoute) => {
|
| | | redirect.value = newRoute.query && newRoute.query.redirect
|
| | |
| | | }
|
| | | }
|
| | |
|
| | | function getUserLoginFacotryList() {
|
| | | if(loginForm.value.username){
|
| | | userLoginFacotryList({userName:loginForm.value.username}).then(res => {
|
| | | console.log('res', res)
|
| | | factoryList.value = res.data
|
| | | })
|
| | | }else {
|
| | | factoryList.value = []
|
| | | }
|
| | | }
|
| | |
|
| | | getCode()
|
| | | getCookie()
|
| | | getUserLoginFacotryList()
|
| | | </script>
|
| | |
|
| | | <style lang='scss' scoped>
|
| | |
| | | <template> |
| | | <div class="app-container analytics-container"> |
| | | <div class="app-container analytics-container" v-loading="loading"> |
| | | |
| | | <!-- å
³é®ææ å¡ç --> |
| | | <el-row :gutter="20" class="metrics-cards"> |
| | |
| | | <component :is="item.icon" /> |
| | | </el-icon> |
| | | </div> |
| | | <div class="card-info"> |
| | | <div class="card-info"> |
| | | <div class="card-number"> |
| | | <el-skeleton-item v-if="loading" variant="text" style="width: 60px; height: 32px;" /> |
| | | <span v-else>{{ item.value }}{{ item.unit }}</span> |
| | | </div> |
| | | <div class="card-label">{{ item.label }}</div> |
| | | <div class="card-trend" :class="item.trend > 0 ? 'positive' : 'negative'" v-if="item.showTrend !== false"> |
| | | <el-icon> |
| | | <component :is="item.trend > 0 ? 'ArrowUp' : 'ArrowDown'" /> |
| | | </el-icon> |
| | | {{ Math.abs(item.trend) }}% |
| | | </div> |
| | | <!-- <div class="card-trend" :class="item.trend > 0 ? 'positive' : 'negative'" v-if="item.showTrend !== false">--> |
| | | <!-- <el-icon>--> |
| | | <!-- <component :is="item.trend > 0 ? 'ArrowUp' : 'ArrowDown'" />--> |
| | | <!-- </el-icon>--> |
| | | <!-- {{ Math.abs(item.trend) }}%--> |
| | | <!-- </div>--> |
| | | </div> |
| | | </div> |
| | | </el-card> |
| | |
| | | |
| | | <!-- 第äºè¡å¾è¡¨ --> |
| | | <el-row :gutter="20" class="charts-section"> |
| | | <!-- ç¼å¶è¾¾æç --> |
| | | <el-col :span="12"> |
| | | <el-card class="chart-card"> |
| | | <template #header> |
| | | <div class="card-header"> |
| | | <span>ç¼å¶è¾¾æç</span> |
| | | <el-tag type="warning">åé¨é¨å¯¹æ¯</el-tag> |
| | | </div> |
| | | </template> |
| | | <div class="chart-container"> |
| | | <div ref="staffingChartRef" class="chart"></div> |
| | | </div> |
| | | </el-card> |
| | | </el-col> |
| | | |
| | | <!-- åå·¥æµå¤±åå åæ --> |
| | | <el-col :span="12"> |
| | | <el-card class="chart-card"> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, onMounted, onUnmounted } from 'vue' |
| | | import { ref, onMounted, onUnmounted, nextTick } from 'vue' |
| | | import { ElMessage } from 'element-plus' |
| | | import { |
| | | Refresh, |
| | | User, |
| | | TrendCharts, |
| | | DataAnalysis, |
| | | PieChart, |
| | | ArrowUp, |
| | | ArrowDown |
| | | } from '@element-plus/icons-vue' |
| | | import * as echarts from 'echarts' |
| | | import { staffOnJobListPage } from '@/api/personnelManagement/employeeRecord.js' |
| | | import {listDept} from "@/api/system/dept.js"; |
| | | import { |
| | | findStaffAnalysisMonthlyTurnoverRateFor12Months, |
| | | findStaffLeaveReasonAnalysis, |
| | | findStaffAnalysisTotalStatistic |
| | | } from "@/api/personnelManagement/staffAnalytics.js"; |
| | | |
| | | // ååºå¼æ°æ® |
| | | const loading = ref(false) |
| | |
| | | trend: 0 |
| | | }, |
| | | { |
| | | label: 'ç¼å¶è¾¾æç', |
| | | value: 0, |
| | | unit: '%', |
| | | icon: 'DataAnalysis', |
| | | type: 'success', |
| | | trend: 0 |
| | | }, |
| | | { |
| | | label: 'å¨èåå·¥æ°', |
| | | value: 0, |
| | | unit: '人', |
| | |
| | | |
| | | // é¨é¨æ°æ® |
| | | const departmentData = ref([]) |
| | | // åå·¥æµå¤±åå åææ°æ® |
| | | const staffLeaveReasons = ref([]) |
| | | // 12个æåå·¥æµå¨æµå¤±çåææ°æ® |
| | | const turnoverRateStatistics = ref([]) |
| | | |
| | | // è·åå¨èåå·¥æ° |
| | | const getStaffCount = async () => { |
| | | // è·åé¨é¨æ°æ® |
| | | const getDepartmentData = async () => { |
| | | try { |
| | | const res = await staffOnJobListPage({ staffState: 1, current: 1, size: 1 }) |
| | | const res = await listDept() |
| | | if (res && res.data) { |
| | | keyMetrics.value[3].value = res.data.total || 0 |
| | | departmentData.value = res.data |
| | | } |
| | | } catch (error) { |
| | | console.error('è·åå¨èåå·¥æ°å¤±è´¥:', error) |
| | | console.error('è·åé¨é¨æ°æ®å¤±è´¥:', error) |
| | | } |
| | | } |
| | | |
| | | const getStaffLeaveReasonAnalysis = async () => { |
| | | try { |
| | | const res = await findStaffLeaveReasonAnalysis() |
| | | if (res && res.data) { |
| | | staffLeaveReasons.value = res.data || [] |
| | | } |
| | | } catch (error) { |
| | | console.error('è·ååå·¥æµå¤±åå åæå¤±è´¥:', error) |
| | | } |
| | | } |
| | | |
| | | // ä¿®æ¹ä¸ºè¿åPromiseç弿¥å½æ° |
| | | const getMonthlyTurnoverRateFor12Months = async () => { |
| | | try { |
| | | const res = await findStaffAnalysisMonthlyTurnoverRateFor12Months() |
| | | if (res && res.data) { |
| | | turnoverRateStatistics.value = res.data || [] |
| | | } |
| | | } catch (error) { |
| | | console.error('è·å12个æåå·¥æµå¨æµå¤±çåææ°æ®å¤±è´¥:', error) |
| | | } |
| | | } |
| | | |
| | | const getStaffAnalysisTotalStatistic = async () => { |
| | | try { |
| | | const res = await findStaffAnalysisTotalStatistic() |
| | | if (res && res.data) { |
| | | keyMetrics.value[0].value = res.data.totalFlowRate || 0 |
| | | keyMetrics.value[1].value = res.data.totalTurnoverRate || 0 |
| | | keyMetrics.value[2].value = res.data.currentOnJobCount || 0 |
| | | } |
| | | } catch (error) { |
| | | console.error('è·åå工忿»ç»è®¡æ°æ®å¤±è´¥:', error) |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | // çææ¨¡ææ°æ® |
| | | const generateMockData = () => { |
| | | // çæå
³é®ææ æ°æ® |
| | | keyMetrics.value[0].value = (Math.random() * 5 + 2).toFixed(1) |
| | | keyMetrics.value[0].trend = (Math.random() * 3 - 1.5).toFixed(1) |
| | | |
| | | keyMetrics.value[1].value = (Math.random() * 3 + 1).toFixed(1) |
| | | keyMetrics.value[1].trend = (Math.random() * 2 - 1).toFixed(1) |
| | | |
| | | keyMetrics.value[2].value = (Math.random() * 15 + 85).toFixed(1) |
| | | keyMetrics.value[2].trend = (Math.random() * 3 - 1.5).toFixed(1) |
| | | |
| | | // çæé¨é¨æ°æ® |
| | | const departments = ['ææ¯é¨', 'éå®é¨', '人äºé¨', 'è´¢å¡é¨', 'ç产é¨', 'å¸åºé¨'] |
| | | departmentData.value = departments.map(dept => ({ |
| | | department: dept, |
| | | currentStaff: Math.floor(Math.random() * 30 + 20), |
| | | plannedStaff: Math.floor(Math.random() * 10 + 35), |
| | | staffingRate: Math.floor(Math.random() * 20 + 80), |
| | | turnoverRate: (Math.random() * 4 + 1).toFixed(1), |
| | | attritionRate: (Math.random() * 2 + 0.5).toFixed(1), |
| | | newHires: Math.floor(Math.random() * 5 + 1), |
| | | resignations: Math.floor(Math.random() * 3 + 1), |
| | | status: Math.random() > 0.7 ? 'å¼å¸¸' : 'æ£å¸¸' |
| | | })) |
| | | } |
| | | |
| | | // å·æ°æ°æ® |
| | | // ä¿®æ¹ä¸ºå¼æ¥å½æ°ï¼ç¡®ä¿æ°æ®å è½½å®æå忏²æå¾è¡¨ |
| | | const refreshData = async () => { |
| | | loading.value = true |
| | | try { |
| | | // 模æAPIè°ç¨å»¶è¿ |
| | | await new Promise(resolve => setTimeout(resolve, 500)) |
| | | |
| | | generateMockData() |
| | | loading.value = true |
| | | |
| | | // çå¾
æææ°æ®å è½½å®æ |
| | | await Promise.all([ |
| | | getDepartmentData(), |
| | | getStaffLeaveReasonAnalysis(), |
| | | getMonthlyTurnoverRateFor12Months(), |
| | | getStaffAnalysisTotalStatistic() |
| | | ]) |
| | | |
| | | await nextTick() |
| | | renderAllCharts() |
| | | |
| | | |
| | | if (!autoRefreshEnabled.value) { |
| | | ElMessage.success('æ°æ®å·æ°æå') |
| | | } |
| | | } catch (error) { |
| | | console.error('å·æ°æ°æ®å¤±è´¥:', error) |
| | | ElMessage.error('å·æ°æ°æ®å¤±è´¥') |
| | | console.error('æ°æ®å·æ°å¤±è´¥:', error) |
| | | ElMessage.error('æ°æ®å·æ°å¤±è´¥') |
| | | } finally { |
| | | loading.value = false |
| | | } |
| | |
| | | if (attritionChartRef.value) { |
| | | attritionChart = echarts.init(attritionChartRef.value) |
| | | } |
| | | |
| | | renderAllCharts() |
| | | |
| | | // åå§åæ¶ä¹å
å è½½æ°æ®å渲æå¾è¡¨ |
| | | refreshData() |
| | | }, 300) |
| | | } |
| | | |
| | |
| | | renderAttritionChart() |
| | | } |
| | | |
| | | // 渲æåå·¥æµå¨çè¶å¿å¾ |
| | | // ä¿®æ¹ä¸ºä½¿ç¨APIè¿åçå®é
æ°æ® |
| | | const renderTurnoverChart = () => { |
| | | if (!turnoverChart) return |
| | | |
| | | const months = ['1æ', '2æ', '3æ', '4æ', '5æ', '6æ', '7æ', '8æ', '9æ', '10æ', '11æ', '12æ'] |
| | | const turnoverData = months.map(() => (Math.random() * 5 + 2).toFixed(1)) |
| | | const attritionData = months.map(() => (Math.random() * 3 + 1).toFixed(1)) |
| | | |
| | | |
| | | // 使ç¨APIè¿åçå®é
æ°æ® |
| | | const months = turnoverRateStatistics.value.map(item => item.month) |
| | | const turnoverData = turnoverRateStatistics.value.map(item => item.flowRate || 0) |
| | | const attritionData = turnoverRateStatistics.value.map(item => item.turnoverRate || 0) |
| | | |
| | | const option = { |
| | | title: { |
| | | text: 'åå·¥æµå¨çè¶å¿', |
| | |
| | | } |
| | | ] |
| | | } |
| | | |
| | | |
| | | turnoverChart.setOption(option) |
| | | } |
| | | |
| | | // 渲æé¨é¨äººååå¸å¾ |
| | | const renderDepartmentChart = () => { |
| | | if (!departmentChart) return |
| | | |
| | | |
| | | const data = departmentData.value.map(item => ({ |
| | | name: item.department, |
| | | value: item.currentStaff |
| | | name: item.deptName, |
| | | value: item.staffCount |
| | | })) |
| | | |
| | | |
| | | const option = { |
| | | title: { |
| | | text: 'é¨é¨äººååå¸', |
| | |
| | | } |
| | | ] |
| | | } |
| | | |
| | | |
| | | departmentChart.setOption(option) |
| | | } |
| | | |
| | | // 渲æç¼å¶è¾¾æçå¾ |
| | | const renderStaffingChart = () => { |
| | | if (!staffingChart) return |
| | | |
| | | const departments = departmentData.value.map(item => item.department) |
| | | |
| | | const departments = departmentData.value.map(item => item.deptName) |
| | | const rates = departmentData.value.map(item => item.staffingRate) |
| | | |
| | | |
| | | const option = { |
| | | title: { |
| | | text: 'ç¼å¶è¾¾æç', |
| | |
| | | } |
| | | ] |
| | | } |
| | | |
| | | |
| | | staffingChart.setOption(option) |
| | | } |
| | | |
| | | // 渲æåå·¥æµå¤±åå åæå¾ |
| | | const renderAttritionChart = () => { |
| | | if (!attritionChart) return |
| | | |
| | | const reasons = ['èªèµå¾
é', 'èä¸åå±', 'å·¥ä½ç¯å¢', '个人åå ', 'å
¶ä»'] |
| | | const data = reasons.map(() => Math.floor(Math.random() * 20 + 5)) |
| | | |
| | | |
| | | const reasons = staffLeaveReasons.value.map(item => item.reasonText) |
| | | const data = staffLeaveReasons.value.map(item => item.count) |
| | | |
| | | const option = { |
| | | title: { |
| | | text: 'åå·¥æµå¤±åå åæ', |
| | |
| | | } |
| | | ] |
| | | } |
| | | |
| | | |
| | | attritionChart.setOption(option) |
| | | } |
| | | |
| | | |
| | | // çå½å¨æ |
| | | onMounted(() => { |
| | | generateMockData() |
| | | getStaffCount() |
| | | initCharts() |
| | | startAutoRefresh() |
| | | }) |
| | |
| | | .analytics-container { |
| | | padding: 10px; |
| | | } |
| | | |
| | | |
| | | .page-header { |
| | | padding: 15px; |
| | | } |
| | | |
| | | |
| | | .page-header h2 { |
| | | font-size: 24px; |
| | | } |
| | | |
| | | |
| | | .header-controls { |
| | | flex-direction: column; |
| | | gap: 15px; |
| | | } |
| | | |
| | | |
| | | .refresh-btn { |
| | | margin-left: 0; |
| | | } |
| | | |
| | | |
| | | .metrics-cards .el-col { |
| | | margin-bottom: 15px; |
| | | } |
| | | |
| | | |
| | | .charts-section .el-col { |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | |
| | | .chart-container { |
| | | height: 300px; |
| | | } |
| | |
| | | .page-header h2 { |
| | | font-size: 20px; |
| | | } |
| | | |
| | | |
| | | .card-number { |
| | | font-size: 24px; |
| | | } |
| | | |
| | | |
| | | .chart-container { |
| | | height: 250px; |
| | | } |
| | |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | <Files ref="filesDia"></Files> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {ref} from "vue"; |
| | | import {staffOnJobInfo} from "@/api/personnelManagement/employeeRecord.js"; |
| | | import {findStaffContractListPage} from "@/api/personnelManagement/staffContract.js"; |
| | | const Files = defineAsyncComponent(() => import( "@/views/personnelManagement/contractManagement/filesDia.vue")); |
| | | const { proxy } = getCurrentInstance() |
| | | const emit = defineEmits(['close']) |
| | | |
| | | const filesDia = ref() |
| | | const dialogFormVisible = ref(false); |
| | | const operationType = ref('') |
| | | const tableColumn = ref([ |
| | | // { |
| | | // label: "ååå¹´é", |
| | | // prop: "contractTerm", |
| | | // }, |
| | | { |
| | | label: "ååå¹´é", |
| | | prop: "contractTerm", |
| | | }, |
| | | { |
| | | label: "ååå¼å§æ¥æ", |
| | | prop: "contractStartTime", |
| | |
| | | { |
| | | label: "ååç»ææ¥æ", |
| | | prop: "contractEndTime", |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: 'right', |
| | | width: 120, |
| | | operation: [ |
| | | { |
| | | name: "ä¸ä¼ éä»¶", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | filesDia.value.openDialog( row,'åå') |
| | | }, |
| | | } |
| | | ], |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | |
| | | operationType.value = type; |
| | | dialogFormVisible.value = true; |
| | | if (operationType.value === 'edit') { |
| | | staffOnJobInfo({staffNo: row.staffNo}).then(res => { |
| | | tableData.value = res.data |
| | | findStaffContractListPage({staffOnJobId: row.id}).then(res => { |
| | | tableData.value = res.data.records |
| | | }) |
| | | } |
| | | } |
| | | |
| | | const openUploadFile = (row) => { |
| | | filesDia.value.open = true |
| | | filesDia.value.row = row |
| | | } |
| | | |
| | | // å
³éå¼¹æ¡ |
| | | const closeDia = () => { |
| | | dialogFormVisible.value = false; |
| | |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | height="500" |
| | | @pagination="paginationSearch" |
| | | :total="page.total" |
| | | > |
| | | </PIMTable> |
| | | <pagination |
| | | style="margin: 10px 0" |
| | | v-show="total > 0" |
| | | @pagination="paginationSearch" |
| | | :total="total" |
| | | :page="page.current" |
| | | :limit="page.size" |
| | | /> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button @click="closeDia">åæ¶</el-button> |
| | |
| | | import { onMounted, ref } from "vue"; |
| | | import FormDia from "@/views/personnelManagement/contractManagement/components/formDia.vue"; |
| | | import { ElMessageBox } from "element-plus"; |
| | | import { staffOnJobListPage } from "@/api/personnelManagement/employeeRecord.js"; |
| | | import { staffOnJobListPage } from "@/api/personnelManagement/staffOnJob.js"; |
| | | import dayjs from "dayjs"; |
| | | import { getToken } from "@/utils/auth.js"; |
| | | import FilesDia from "./filesDia.vue"; |
| | |
| | | clickFun: (row) => { |
| | | openForm("edit", row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "éä»¶", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | openFilesFormDia(row); |
| | | }, |
| | | }, |
| | | } |
| | | ], |
| | | }, |
| | | ]); |
| | |
| | | tableLoading.value = true; |
| | | const params = { ...searchForm.value, ...page }; |
| | | params.entryDate = undefined |
| | | params.staffState = 1 |
| | | staffOnJobListPage(params).then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records |
| | |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | proxy.download("/staff/staffOnJob/export", {}, "åå管ç.xlsx"); |
| | | proxy.download("/staff/staffOnJob/export", {staffState: 1}, "åå管ç.xlsx"); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | |
| | | <!-- å工信æ¯å±ç¤ºåºå --> |
| | | <div class="info-section"> |
| | | <div class="info-title">å工信æ¯</div> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <div class="info-item"> |
| | | <span class="info-label">å§åï¼</span> |
| | | <el-select v-model="form.staffName" placeholder="è¯·éæ©äººå" style="width: 100%" @change="handleSelect"> |
| | | <el-option |
| | | v-for="item in personList" |
| | | :key="item.id" |
| | | :label="item.staffName" |
| | | :value="item.staffName" |
| | | <el-form :model="form" label-width="200px" label-position="left" :rules="rules" ref="formRef" style="margin-top: 20px"> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å§åï¼" prop="staffOnJobId"> |
| | | <el-select v-model="form.staffOnJobId" |
| | | placeholder="è¯·éæ©äººå" |
| | | style="width: 100%" |
| | | :disabled="operationType === 'edit'" |
| | | @change="handleSelect"> |
| | | <el-option |
| | | v-for="item in personList" |
| | | :key="item.id" |
| | | :label="item.staffName" |
| | | :value="item.id" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="åå·¥ç¼å·ï¼"> |
| | | {{ currentStaffRecord.staffNo || '-' }} |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ§å«ï¼"> |
| | | {{ currentStaffRecord.sex || '-' }} |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ·ç±ä½åï¼"> |
| | | {{ currentStaffRecord.nativePlace || '-' }} |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å²ä½ï¼"> |
| | | {{ currentStaffRecord.postName || '-' }} |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç°ä½åï¼"> |
| | | {{ currentStaffRecord.adress || '-' }} |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="第ä¸å¦åï¼"> |
| | | {{ currentStaffRecord.firstStudy || '-' }} |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ä¸ä¸ï¼"> |
| | | {{ currentStaffRecord.profession || '-' }} |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å¹´é¾ï¼"> |
| | | {{ currentStaffRecord.age || '-' }} |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="èç³»çµè¯ï¼"> |
| | | {{ currentStaffRecord.phone || '-' }} |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç´§æ¥è系人ï¼"> |
| | | {{ currentStaffRecord.emergencyContact || '-' }} |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç´§æ¥è系人èç³»çµè¯ï¼"> |
| | | {{ currentStaffRecord.emergencyContactPhone || '-' }} |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="离èåå ï¼" prop="reason"> |
| | | <el-select v-model="form.reason" placeholder="è¯·éæ©ç¦»èåå " style="width: 100%" @change="handleSelectDimissionReason"> |
| | | <el-option |
| | | v-for="(item, index) in dimissionReasonOptions" |
| | | :key="index" |
| | | :label="item.label" |
| | | :value="item.value" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="夿³¨ï¼" prop="remark" v-if="form.reason === 'other'"> |
| | | <el-input |
| | | v-model="form.remark" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="夿³¨" |
| | | maxlength="500" |
| | | show-word-limit |
| | | /> |
| | | </el-select> |
| | | </div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="info-item"> |
| | | <span class="info-label">åå·¥ç¼å·ï¼</span> |
| | | <span class="info-value">{{ form.staffNo || '-' }}</span> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <div class="info-item"> |
| | | <span class="info-label">æ§å«ï¼</span> |
| | | <span class="info-value">{{ form.sex || '-' }}</span> |
| | | </div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="info-item"> |
| | | <span class="info-label">æ·ç±ä½åï¼</span> |
| | | <span class="info-value">{{ form.nativePlace || '-' }}</span> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <div class="info-item"> |
| | | <span class="info-label">å²ä½ï¼</span> |
| | | <span class="info-value">{{ form.postJob || '-' }}</span> |
| | | </div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="info-item"> |
| | | <span class="info-label">ç°ä½åï¼</span> |
| | | <span class="info-value">{{ form.adress || '-' }}</span> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <div class="info-item"> |
| | | <span class="info-label">第ä¸å¦åï¼</span> |
| | | <span class="info-value">{{ form.firstStudy || '-' }}</span> |
| | | </div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="info-item"> |
| | | <span class="info-label">ä¸ä¸ï¼</span> |
| | | <span class="info-value">{{ form.profession || '-' }}</span> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <div class="info-item"> |
| | | <span class="info-label">å¹´é¾ï¼</span> |
| | | <span class="info-value">{{ form.age || '-' }}</span> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <div class="info-item"> |
| | | <span class="info-label">èç³»çµè¯ï¼</span> |
| | | <span class="info-value">{{ form.phone || '-' }}</span> |
| | | </div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="info-item"> |
| | | <span class="info-label">ç´§æ¥è系人ï¼</span> |
| | | <span class="info-value">{{ form.emergencyContact || '-' }}</span> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <div class="info-item"> |
| | | <span class="info-label">ç´§æ¥è系人èç³»çµè¯ï¼</span> |
| | | <span class="info-value">{{ form.emergencyContactPhone || '-' }}</span> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <div class="info-item"> |
| | | <span class="info-label">ååå¼å§æ¥æï¼</span> |
| | | <span class="info-value">{{ form.contractStartTime || '-' }}</span> |
| | | </div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="info-item"> |
| | | <span class="info-label">ååç»ææ¥æï¼</span> |
| | | <span class="info-value">{{ form.contractEndTime || '-' }}</span> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | |
| | | <!-- <el-row :gutter="30">--> |
| | | <!-- <el-col :span="12">--> |
| | | <!-- <div class="info-item">--> |
| | | <!-- <span class="info-label">离èåå ï¼</span>--> |
| | | <!-- <el-select v-model="form.reason" placeholder="è¯·éæ©äººå" style="width: 100%" @change="handleSelect">--> |
| | | <!-- <el-option--> |
| | | <!-- v-for="(item, index) in dimissionReasonOptions"--> |
| | | <!-- :key="index"--> |
| | | <!-- :label="item.label"--> |
| | | <!-- :value="item.value"--> |
| | | <!-- />--> |
| | | <!-- </el-select>--> |
| | | <!-- </div>--> |
| | | <!-- </el-col>--> |
| | | <!-- <el-col :span="12">--> |
| | | <!-- <div class="info-item">--> |
| | | <!-- <span class="info-label">åå·¥ç¼å·ï¼</span>--> |
| | | <!-- <span class="info-value">{{ form.staffNo || '-' }}</span>--> |
| | | <!-- </div>--> |
| | | <!-- </el-col>--> |
| | | <!-- </el-row>--> |
| | | </div> |
| | | |
| | | <!-- 离èä¿¡æ¯å¡«ååºå --> |
| | | <!-- <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef" style="margin-top: 20px"> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç¦»èæ¥æï¼" prop="dimissionDate"> |
| | | <el-date-picker |
| | | v-model="form.dimissionDate" |
| | | type="date" |
| | | placeholder="è¯·éæ©ç¦»èæ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | clearable |
| | | style="width: 100%" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="离èåå ï¼" prop="dimissionReason"> |
| | | <el-input |
| | | v-model="form.dimissionReason" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请è¾å
¥ç¦»èåå " |
| | | maxlength="500" |
| | | show-word-limit |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> --> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="submitForm">确认</el-button> |
| | |
| | | |
| | | <script setup> |
| | | import {ref, reactive, toRefs, getCurrentInstance} from "vue"; |
| | | import {getStaffJoinInfo, staffJoinAdd, staffJoinUpdate} from "@/api/personnelManagement/onboarding.js"; |
| | | import { staffOnJobListPage } from "@/api/personnelManagement/employeeRecord.js"; |
| | | import {staffOnJobListPage} from "@/api/personnelManagement/staffOnJob.js"; |
| | | import {createStaffLeave, updateStaffLeave} from "@/api/personnelManagement/staffLeave.js"; |
| | | const { proxy } = getCurrentInstance() |
| | | const emit = defineEmits(['close']) |
| | | |
| | |
| | | const operationType = ref('') |
| | | const data = reactive({ |
| | | form: { |
| | | staffNo: "", |
| | | staffName: "", |
| | | sex: "", |
| | | nativePlace: "", |
| | | postJob: "", |
| | | adress: "", |
| | | firstStudy: "", |
| | | profession: "", |
| | | age: 0, |
| | | phone: "", |
| | | emergencyContact: "", |
| | | emergencyContactPhone: "", |
| | | contractTerm: 0, |
| | | contractStartTime: "", |
| | | contractEndTime: "", |
| | | dimissionDate: "", |
| | | dimissionReason: "", |
| | | staffState: "", |
| | | staffOnJobId: undefined, |
| | | reason: "", |
| | | remark: "", |
| | | }, |
| | | rules: { |
| | | staffName: [{ required: true, message: "è¯·éæ©äººå", trigger: "change" }], |
| | | dimissionDate: [{ required: true, message: "è¯·éæ©ç¦»èæ¥æ", trigger: "change" }], |
| | | dimissionReason: [{ required: true, message: "请è¾å
¥ç¦»èåå ", trigger: "blur" }], |
| | | staffName: [{ required: true, message: "è¯·éæ©äººå" }], |
| | | reason: [{ required: true, message: "è¯·éæ©ç¦»èåå "}], |
| | | }, |
| | | dimissionReasonOptions: [ |
| | | {label: 'èªèµå¾
é', value: 'salary'}, |
| | | {label: 'èä¸åå±', value: 'career_development'}, |
| | | {label: 'å·¥ä½ç¯å¢', value: 'work_environment'}, |
| | | {label: '个人åå ', value: 'personal_reason'}, |
| | | {label: 'å
¶ä»', value: 'other'}, |
| | | ], |
| | | currentStaffRecord: {}, |
| | | }); |
| | | const { form, rules } = toRefs(data); |
| | | const { form, rules, dimissionReasonOptions, currentStaffRecord } = toRefs(data); |
| | | |
| | | // æå¼å¼¹æ¡ |
| | | const openDialog = (type, row) => { |
| | | getList() |
| | | operationType.value = type; |
| | | dialogFormVisible.value = true; |
| | | if (operationType.value === 'edit') { |
| | | getStaffJoinInfo(row.id).then(res => { |
| | | form.value = {...res.data} |
| | | }) |
| | | currentStaffRecord.value = row |
| | | form.value.staffOnJobId = row.staffOnJobId |
| | | form.value.reason = row.reason |
| | | form.value.remark = row.remark |
| | | personList.value = [ |
| | | { |
| | | staffName: row.staffName, |
| | | id: row.staffOnJobId, |
| | | } |
| | | ] |
| | | } else { |
| | | getList() |
| | | } |
| | | } |
| | | |
| | | const handleSelectDimissionReason = (val) => { |
| | | if (val === 'other') { |
| | | form.value.remark = '' |
| | | } |
| | | } |
| | | // æäº¤äº§å表å |
| | | const submitForm = () => { |
| | | // 表å已注éï¼ç´æ¥æäº¤ï¼ä¸è¿è¡éªè¯ |
| | | if (!form.value.staffName) { |
| | | proxy.$modal.msgError("è¯·éæ©äººå"); |
| | | return; |
| | | } |
| | | form.value.staffState = 0 |
| | | if (operationType.value === "add") { |
| | | staffJoinAdd(form.value).then(res => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeDia(); |
| | | }) |
| | | } else { |
| | | staffJoinUpdate(form.value).then(res => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeDia(); |
| | | }) |
| | | if (form.value.reason !== 'other') { |
| | | form.value.remark = '' |
| | | } |
| | | proxy.$refs["formRef"].validate(valid => { |
| | | if (valid) { |
| | | if (operationType.value === "add") { |
| | | createStaffLeave(form.value).then(res => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeDia(); |
| | | }) |
| | | } else { |
| | | updateStaffLeave(currentStaffRecord.value.id, form.value).then(res => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeDia(); |
| | | }) |
| | | } |
| | | } |
| | | }) |
| | | |
| | | } |
| | | // å
³éå¼¹æ¡ |
| | | const closeDia = () => { |
| | | // 表å已注éï¼æå¨éç½®è¡¨åæ°æ® |
| | | form.value = { |
| | | staffNo: "", |
| | | staffName: "", |
| | | sex: "", |
| | | nativePlace: "", |
| | | postJob: "", |
| | | adress: "", |
| | | firstStudy: "", |
| | | profession: "", |
| | | age: 0, |
| | | phone: "", |
| | | emergencyContact: "", |
| | | emergencyContactPhone: "", |
| | | contractTerm: 0, |
| | | contractStartTime: "", |
| | | contractEndTime: "", |
| | | dimissionDate: "", |
| | | dimissionReason: "", |
| | | staffState: "", |
| | | staffOnJobId: undefined, |
| | | reason: "", |
| | | remark: "", |
| | | }; |
| | | dialogFormVisible.value = false; |
| | | emit('close') |
| | |
| | | }; |
| | | |
| | | const handleSelect = (val) => { |
| | | let obj = personList.value.find(item => item.staffName === val) |
| | | let obj = personList.value.find(item => item.id === val) |
| | | currentStaffRecord.value = {} |
| | | if (obj) { |
| | | let { |
| | | sex, |
| | | phone, |
| | | staffNo, |
| | | nativePlace, |
| | | postJob, |
| | | adress, |
| | | firstStudy, |
| | | profession, |
| | | age, |
| | | emergencyContact, |
| | | emergencyContactPhone, |
| | | contractTerm, |
| | | contractStartTime, |
| | | contractEndTime, |
| | | staffName |
| | | } = obj |
| | | // ä¿çç¦»èæ¥æå离èåå ï¼åªæ´æ°åå·¥ä¿¡æ¯ |
| | | form.value = { |
| | | ...form.value, |
| | | sex, |
| | | phone, |
| | | staffNo, |
| | | nativePlace, |
| | | postJob, |
| | | adress, |
| | | firstStudy, |
| | | profession, |
| | | age, |
| | | emergencyContact, |
| | | emergencyContactPhone, |
| | | contractTerm, |
| | | contractStartTime, |
| | | contractEndTime, |
| | | staffName |
| | | } |
| | | currentStaffRecord.value = obj |
| | | } |
| | | } |
| | | defineExpose({ |
| | |
| | | clearable |
| | | :prefix-icon="Search" |
| | | /> |
| | | <span style="margin-left: 10px;" class="search_title">ååå¼å§æ¥æï¼</span> |
| | | <el-date-picker |
| | | v-model="searchForm.entryDateStart" |
| | | type="date" |
| | | placeholder="è¯·éæ©ååå¼å§æ¥æ" |
| | | size="default" |
| | | @change="(date) => handleDateChange(date,1)" |
| | | /> |
| | | <span style="margin-left: 10px;" class="search_title">ååç»ææ¥æï¼</span> |
| | | <el-date-picker |
| | | v-model="searchForm.entryDateEnd" |
| | | type="date" |
| | | placeholder="è¯·éæ©ååç»ææ¥æ" |
| | | size="default" |
| | | @change="(date) => handleDateChange(date,2)" |
| | | /> |
| | | <el-button type="primary" @click="handleQuery" style="margin-left: 10px" |
| | | >æç´¢</el-button |
| | | > |
| | |
| | | import { Search } from "@element-plus/icons-vue"; |
| | | import {onMounted, ref} from "vue"; |
| | | import FormDia from "@/views/personnelManagement/dimission/components/formDia.vue"; |
| | | import {staffJoinDel, staffJoinListPage} from "@/api/personnelManagement/onboarding.js"; |
| | | import {findStaffLeaveListPage, batchDeleteStaffLeaves} from "@/api/personnelManagement/staffLeave.js"; |
| | | import {ElMessageBox} from "element-plus"; |
| | | import dayjs from "dayjs"; |
| | | |
| | | const data = reactive({ |
| | | searchForm: { |
| | |
| | | prop: "nativePlace", |
| | | }, |
| | | { |
| | | label: "é¨é¨", |
| | | prop: "deptName", |
| | | }, |
| | | { |
| | | label: "å²ä½", |
| | | prop: "postJob", |
| | | prop: "postName", |
| | | }, |
| | | { |
| | | label: "ç°ä½å", |
| | |
| | | prop: "emergencyContactPhone", |
| | | width:150 |
| | | }, |
| | | // { |
| | | // label: "ååå¹´é", |
| | | // prop: "contractTerm", |
| | | // }, |
| | | { |
| | | label: "ååå¼å§æ¥æ", |
| | | prop: "contractStartTime", |
| | | width: 120 |
| | | }, |
| | | { |
| | | label: "ååç»ææ¥æ", |
| | | prop: "contractEndTime", |
| | | width: 120 |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: 'right', |
| | | operation: [ |
| | | { |
| | | name: "ç¼è¾", |
| | |
| | | const { proxy } = getCurrentInstance() |
| | | |
| | | |
| | | const handleDateChange = (value,type) => { |
| | | searchForm.value.entryDateEnd = null |
| | | searchForm.value.entryDateStart = null |
| | | if(type === 1){ |
| | | if (value) { |
| | | searchForm.value.entryDateStart = dayjs(value).format("YYYY-MM-DD"); |
| | | } |
| | | }else{ |
| | | if (value) { |
| | | searchForm.value.entryDateEnd = dayjs(value).format("YYYY-MM-DD"); |
| | | } |
| | | } |
| | | getList(); |
| | | }; |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | |
| | | }; |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | staffJoinListPage({...page, ...searchForm.value, staffState: 0}).then(res => { |
| | | findStaffLeaveListPage({...page, ...searchForm.value}).then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records |
| | | page.total = res.data.total; |
| | |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | staffJoinDel(ids).then((res) => { |
| | | batchDeleteStaffLeaves(ids).then((res) => { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | getList(); |
| | | }); |
| | |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | proxy.download("/staff/staffJoinLeaveRecord/export", {staffState: 0}, "人å离è.xlsx"); |
| | | proxy.download("/staff/staffLeave/export", {}, "人å离è.xlsx"); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| ÎļþÃû´Ó src/views/personnelManagement/onboarding/components/formDia.vue ÐÞ¸Ä |
| | |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å²ä½ï¼" prop="postJob"> |
| | | <el-input v-model="form.postJob" placeholder="请è¾å
¥" clearable/> |
| | | <el-form-item label="å²ä½ï¼" prop="sysPostId"> |
| | | <el-select v-model="form.sysPostId" placeholder="è¯·éæ©å²ä½" clearable> |
| | | <el-option |
| | | v-for="item in postOptions" |
| | | :key="item.postId" |
| | | :label="item.postName" |
| | | :value="item.postId" |
| | | :disabled="item.status === '1'" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç°ä½åï¼" prop="adress"> |
| | | <el-input v-model="form.adress" placeholder="请è¾å
¥" clearable/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="é¨é¨ï¼" prop="sysDeptId"> |
| | | <el-tree-select |
| | | v-model="form.sysDeptId" |
| | | :data="deptOptions" |
| | | :props="{ value: 'id', label: 'label', children: 'children' }" |
| | | value-key="id" |
| | | placeholder="è¯·éæ©é¨é¨" |
| | | check-strictly |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å¹´é¾ï¼" prop="age"> |
| | | <el-input-number v-model="form.age" :precision="0" :step="1" style="width: 100%"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | |
| | | <el-col :span="12"> |
| | | <el-form-item label="ä¸ä¸ï¼" prop="profession"> |
| | | <el-input v-model="form.profession" placeholder="请è¾å
¥" clearable/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å¹´é¾ï¼" prop="age"> |
| | | <el-input-number v-model="form.age" :precision="0" :step="1" style="width: 100%"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {ref} from "vue"; |
| | | import {getStaffJoinInfo, staffJoinAdd, staffJoinUpdate} from "@/api/personnelManagement/onboarding.js"; |
| | | import {ref, onMounted} from "vue"; |
| | | import {findPostOptions} from "@/api/system/post.js"; |
| | | import {listDept} from "@/api/system/dept.js"; |
| | | import {staffOnJobInfo, createStaffOnJob, updateStaffOnJob} from "@/api/personnelManagement/staffOnJob.js"; |
| | | import {deptTreeSelect} from "@/api/system/user.js"; |
| | | const { proxy } = getCurrentInstance() |
| | | const emit = defineEmits(['close']) |
| | | |
| | | const dialogFormVisible = ref(false); |
| | | const operationType = ref('') |
| | | const id = ref(0) |
| | | const data = reactive({ |
| | | form: { |
| | | staffNo: "", |
| | |
| | | contractStartTime: "", |
| | | contractEndTime: "", |
| | | staffState: "", |
| | | sysPostId: undefined, |
| | | sysDeptId: undefined, |
| | | }, |
| | | rules: { |
| | | staffNo: [{ required: true, message: "请è¾å
¥", trigger: "blur" },], |
| | |
| | | contractStartTime: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | contractEndTime: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | }, |
| | | postOptions: [], // å²ä½é项 |
| | | deptOptions: [], // é¨é¨é项 |
| | | }); |
| | | const { form, rules } = toRefs(data); |
| | | const { form, rules, postOptions, deptOptions } = toRefs(data); |
| | | |
| | | // æå¼å¼¹æ¡ |
| | | const openDialog = (type, row) => { |
| | | operationType.value = type; |
| | | dialogFormVisible.value = true; |
| | | if (operationType.value === 'edit') { |
| | | getStaffJoinInfo(row.id).then(res => { |
| | | id.value = row.id |
| | | staffOnJobInfo(id.value, {}).then(res => { |
| | | form.value = {...res.data} |
| | | if (form.value.sysPostId === 0) { |
| | | form.value.sysPostId = undefined |
| | | } |
| | | // ç¼è¾æ¶ä¹è®¡ç®ä¸æ¬¡ååå¹´é |
| | | calculateContractTerm(); |
| | | }) |
| | | } else { |
| | | form.value.id = '' |
| | | } |
| | | |
| | | } |
| | | onMounted(() => { |
| | | fetchPostOptions() |
| | | fetchDeptOptions() |
| | | }) |
| | | |
| | | const fetchPostOptions = () => { |
| | | findPostOptions().then(res => { |
| | | postOptions.value = res.data |
| | | }) |
| | | } |
| | | |
| | | // æ¥è¯¢é¨é¨å表 |
| | | const fetchDeptOptions = () => { |
| | | deptTreeSelect().then(response => { |
| | | deptOptions.value = filterDisabledDept(JSON.parse(JSON.stringify(response.data))) |
| | | }) |
| | | } |
| | | |
| | | /** è¿æ»¤ç¦ç¨çé¨é¨ */ |
| | | function filterDisabledDept(deptList) { |
| | | return deptList.filter(dept => { |
| | | if (dept.disabled) { |
| | | return false |
| | | } |
| | | if (dept.children && dept.children.length) { |
| | | dept.children = filterDisabledDept(dept.children) |
| | | } |
| | | return true |
| | | }) |
| | | } |
| | | |
| | | // æäº¤äº§å表å |
| | | const submitForm = () => { |
| | | if (!form.value.sysPostId) { |
| | | form.value.sysPostId = 0; |
| | | } |
| | | proxy.$refs.formRef.validate(valid => { |
| | | if (valid) { |
| | | form.value.staffState = 1 |
| | | if (operationType.value === "add") { |
| | | staffJoinAdd(form.value).then(res => { |
| | | createStaffOnJob(form.value).then(res => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeDia(); |
| | | }) |
| | | } else { |
| | | staffJoinUpdate(form.value).then(res => { |
| | | updateStaffOnJob(id.value, form.value).then(res => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeDia(); |
| | | }) |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <el-dialog |
| | | v-model="isShow" |
| | | title="ç»ç¾åå" |
| | | width="800px" |
| | | @close="closeModal" |
| | | > |
| | | <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef"> |
| | | <el-form-item label="ååå¼å§æ¥æï¼" prop="contractStartTime"> |
| | | <el-date-picker |
| | | v-model="form.contractStartTime" |
| | | type="date" |
| | | placeholder="è¯·éæ©æ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | clearable |
| | | style="width: 100%" |
| | | @change="calculateContractTerm" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="ååç»ææ¥æï¼" prop="contractEndTime"> |
| | | <el-date-picker |
| | | v-model="form.contractEndTime" |
| | | type="date" |
| | | placeholder="è¯·éæ©æ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | clearable |
| | | style="width: 100%" |
| | | @change="calculateContractTerm" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="ååå¹´éï¼" prop="contractTerm"> |
| | | <el-input-number v-model="form.contractTerm" :precision="0" :step="1" style="width: 100%" :disabled="true"/> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="submitForm">确认</el-button> |
| | | <el-button @click="closeModal">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | | // ç»ç¾åå |
| | | import { renewContract } from "@/api/personnelManagement/staffOnJob.js"; |
| | | import {computed, getCurrentInstance,} from "vue"; |
| | | |
| | | const emit = defineEmits(['update:visible', 'completed']); |
| | | |
| | | const data = reactive({ |
| | | form: { |
| | | contractTerm: 0, |
| | | contractStartTime: "", |
| | | contractEndTime: "", |
| | | }, |
| | | rules: { |
| | | contractTerm: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | contractStartTime: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | contractEndTime: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | } |
| | | }); |
| | | const { form, rules } = toRefs(data); |
| | | let { proxy } = getCurrentInstance() |
| | | |
| | | const props = defineProps({ |
| | | id: { |
| | | type: Number, |
| | | default: 0, |
| | | }, |
| | | |
| | | visible: { |
| | | type: Boolean, |
| | | required: true, |
| | | }, |
| | | }) |
| | | |
| | | const isShow = computed({ |
| | | get() { |
| | | return props.visible; |
| | | }, |
| | | set(val) { |
| | | emit('update:visible', val); |
| | | }, |
| | | }); |
| | | |
| | | // 计ç®ååå¹´é |
| | | const calculateContractTerm = () => { |
| | | if (form.value.contractStartTime && form.value.contractEndTime) { |
| | | const startDate = new Date(form.value.contractStartTime); |
| | | const endDate = new Date(form.value.contractEndTime); |
| | | |
| | | if (endDate > startDate) { |
| | | // 计ç®å¹´ä»½å·® |
| | | const yearDiff = endDate.getFullYear() - startDate.getFullYear(); |
| | | const monthDiff = endDate.getMonth() - startDate.getMonth(); |
| | | const dayDiff = endDate.getDate() - startDate.getDate(); |
| | | |
| | | let years = yearDiff; |
| | | |
| | | // å¦æç»ææ¥æçææ¥å°äºå¼å§æ¥æçææ¥ï¼ååå»1å¹´ |
| | | if (monthDiff < 0 || (monthDiff === 0 && dayDiff < 0)) { |
| | | years = yearDiff - 1; |
| | | } |
| | | |
| | | form.value.contractTerm = Math.max(0, years); |
| | | } else { |
| | | form.value.contractTerm = 0; |
| | | } |
| | | } else { |
| | | form.value.contractTerm = 0; |
| | | } |
| | | }; |
| | | |
| | | const submitForm = () => { |
| | | proxy.$refs["formRef"].validate(valid => { |
| | | if (valid) { |
| | | renewContract(props.id, form.value).then(res => { |
| | | if (res.code === 200) { |
| | | proxy.$modal.msgSuccess("ç»ç¾ååæå"); |
| | | emit('completed'); |
| | | closeModal(); |
| | | } |
| | | }) |
| | | } |
| | | }) |
| | | } |
| | | |
| | | // å
³éå¼¹æ¡ |
| | | const closeModal = () => { |
| | | // éç½®è¡¨åæ°æ® |
| | | form.value = { |
| | | contractTerm: 0, |
| | | contractStartTime: "", |
| | | contractEndTime: "", |
| | | }; |
| | | isShow.value = false; |
| | | }; |
| | | </script> |
| ÎļþÃû´Ó src/views/personnelManagement/employeeRecord/components/formDia.vue ÐÞ¸Ä |
| | |
| | | |
| | | <script setup> |
| | | import {ref} from "vue"; |
| | | import {staffOnJobInfo} from "@/api/personnelManagement/employeeRecord.js"; |
| | | import {staffOnJobInfo} from "@/api/personnelManagement/staffOnJob.js"; |
| | | const { proxy } = getCurrentInstance() |
| | | const emit = defineEmits(['close']) |
| | | |
| | |
| | | > |
| | | </div> |
| | | <div> |
| | | <!-- <el-button type="primary" @click="openForm('add')">æ°å¢å
¥è</el-button>--> |
| | | <el-button type="primary" @click="openFormNewOrEditFormDia('add')">æ°å¢å
¥è</el-button> |
| | | <el-button @click="handleOut">导åº</el-button> |
| | | <!-- <el-button type="danger" plain @click="handleDelete">å é¤</el-button>--> |
| | | <el-button type="danger" plain @click="handleDelete">å é¤</el-button> |
| | | </div> |
| | | </div> |
| | | <div class="table_list"> |
| | |
| | | :total="page.total" |
| | | ></PIMTable> |
| | | </div> |
| | | <form-dia ref="formDia" @close="handleQuery"></form-dia> |
| | | <show-form-dia ref="formDia" @close="handleQuery"></show-form-dia> |
| | | <new-or-edit-form-dia ref="formDiaNewOrEditFormDia" @close="handleQuery"></new-or-edit-form-dia> |
| | | <renew-contract |
| | | v-if="isShowRenewContractModal" |
| | | v-model:visible="isShowRenewContractModal" |
| | | :id="id" |
| | | @completed="handleQuery" |
| | | /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { Search } from "@element-plus/icons-vue"; |
| | | import {onMounted, ref} from "vue"; |
| | | import FormDia from "@/views/personnelManagement/employeeRecord/components/formDia.vue"; |
| | | import {ElMessageBox} from "element-plus"; |
| | | import {staffOnJobListPage} from "@/api/personnelManagement/employeeRecord.js"; |
| | | import {batchDeleteStaffOnJobs, staffOnJobListPage} from "@/api/personnelManagement/staffOnJob.js"; |
| | | import dayjs from "dayjs"; |
| | | const NewOrEditFormDia = defineAsyncComponent(() => import("@/views/personnelManagement/employeeRecord/components/NewOrEditFormDia.vue")); |
| | | const ShowFormDia = defineAsyncComponent(() => import( "@/views/personnelManagement/employeeRecord/components/Show.vue")); |
| | | const RenewContract = defineAsyncComponent(() => import( "@/views/personnelManagement/employeeRecord/components/RenewContract.vue")); |
| | | |
| | | const data = reactive({ |
| | | searchForm: { |
| | |
| | | }, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | const isShowRenewContractModal = ref(false); |
| | | const id = ref(0); |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "ç¶æ", |
| | |
| | | { |
| | | label: "æ·ç±ä½å", |
| | | prop: "nativePlace", |
| | | }, |
| | | { |
| | | label: "é¨é¨", |
| | | prop: "deptName", |
| | | }, |
| | | { |
| | | label: "å²ä½", |
| | |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: 'right', |
| | | width: 180, |
| | | operation: [ |
| | | { |
| | | name: "详æ
", |
| | | name: "ç¼è¾", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | openForm("edit", row); |
| | | openFormNewOrEditFormDia("edit", row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "ç»ç¾åå", |
| | | type: "text", |
| | | showHide: row => row.staffState === 1, |
| | | clickFun: (row) => { |
| | | isShowRenewContractModal.value = true; |
| | | id.value = row.id; |
| | | }, |
| | | }, |
| | | // { |
| | | // name: "详æ
", |
| | | // type: "text", |
| | | // clickFun: (row) => { |
| | | // openForm("edit", row); |
| | | // }, |
| | | // }, |
| | | ], |
| | | }, |
| | | ]); |
| | |
| | | total: 0 |
| | | }); |
| | | const formDia = ref() |
| | | const formDiaNewOrEditFormDia = ref() |
| | | const { proxy } = getCurrentInstance() |
| | | |
| | | const changeDaterange = (value) => { |
| | |
| | | tableLoading.value = true; |
| | | const params = { ...searchForm.value, ...page }; |
| | | params.entryDate = undefined |
| | | staffOnJobListPage({...params, staffState: 1}).then(res => { |
| | | staffOnJobListPage({...params}).then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records |
| | | page.total = res.data.total; |
| | |
| | | formDia.value?.openDialog(type, row) |
| | | }) |
| | | }; |
| | | const openFormNewOrEditFormDia = (type, row) => { |
| | | nextTick(() => { |
| | | formDiaNewOrEditFormDia.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(() => { |
| | | batchDeleteStaffOnJobs(ids).then((res) => { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | getList(); |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | |
| | | // å¯¼åº |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | proxy.download("/staff/staffOnJob/export", {staffState: 1}, "å¨èåå·¥å°è´¦.xlsx"); |
| | | proxy.download("/staff/staffOnJob/export", {staffState: 1}, "åå·¥å°è´¦.xlsx"); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | |
| | | |
| | | <script setup> |
| | | import {ref} from "vue"; |
| | | import {getStaffJoinInfo, getStaffOnJob, staffJoinAdd, staffJoinUpdate} from "@/api/personnelManagement/onboarding.js"; |
| | | import {compensationAdd, compensationUpdate} from "@/api/personnelManagement/payrollManagement.js"; |
| | | import {staffOnJobInfo, staffOnJobListPage} from "@/api/personnelManagement/staffOnJob.js"; |
| | | const { proxy } = getCurrentInstance() |
| | | const emit = defineEmits(['close']) |
| | | |
| | |
| | | const openDialog = (type, row) => { |
| | | operationType.value = type; |
| | | dialogFormVisible.value = true; |
| | | getStaffOnJob().then(res => { |
| | | personList.value = res.data |
| | | }) |
| | | staffOnJobListPage({ |
| | | current: -1, |
| | | size: -1, |
| | | staffState: 1 |
| | | }).then(res => { |
| | | personList.value = res.data.records || [] |
| | | }) |
| | | form.value = {} |
| | | if (operationType.value === 'edit') { |
| | | getStaffJoinInfo(row.id).then(res => { |
| | | staffOnJobInfo(row.staffId).then(res => { |
| | | form.value = {...row} |
| | | form.value.payDate = form.value.payDate + '-01' |
| | | }) |
| | |
| | | import { Search } from "@element-plus/icons-vue"; |
| | | import {onMounted, ref, reactive, toRefs, getCurrentInstance, nextTick} from "vue"; |
| | | import FormDia from "@/views/personnelManagement/payrollManagement/components/formDia.vue"; |
| | | import {staffJoinDel} from "@/api/personnelManagement/onboarding.js"; |
| | | import {ElMessageBox} from "element-plus"; |
| | | import dayjs from "dayjs"; |
| | | import {compensationDelete, compensationListPage} from "@/api/personnelManagement/payrollManagement.js"; |
| | |
| | | import {useDict} from "@/utils/dict.js" |
| | | import {Plus, Download, Search, Refresh} from '@element-plus/icons-vue' |
| | | import {save, del, delByIds, listPage} from "@/api/personnelManagement/scheduling.js" |
| | | import {getStaffOnJob} from "@/api/personnelManagement/onboarding.js"; |
| | | import dayjs from "dayjs"; |
| | | import pagination from "@/components/PIMTable/Pagination.vue"; |
| | | import {staffOnJobListPage} from "@/api/personnelManagement/staffOnJob.js"; |
| | | |
| | | const { proxy } = getCurrentInstance(); |
| | | |
| | |
| | | * è·åå½åå¨è人åå表 |
| | | */ |
| | | const getPersonList = () => { |
| | | getStaffOnJob().then(res => { |
| | | personList.value = res.data |
| | | staffOnJobListPage({ |
| | | current: -1, |
| | | size: -1, |
| | | staffState: 1 |
| | | }).then(res => { |
| | | personList.value = res.data.records || [] |
| | | }) |
| | | }; |
| | | const paginationChange = (obj) => { |
| | |
| | | |
| | | const { proxy } = getCurrentInstance() |
| | | import { getUserProfile } from '@/api/system/user.js' |
| | | import {staffJoinUpdate, staffJoinListPage} from "@/api/personnelManagement/onboarding.js"; |
| | | import { fa, id } from 'element-plus/es/locales.mjs' |
| | | import {staffOnJobListPage, updateStaffOnJob} from "@/api/personnelManagement/staffOnJob.js"; |
| | | |
| | | const tableLoading = ref(false) |
| | | // å页忰 |
| | |
| | | currentUser.value = res.data |
| | | // console.log("----",currentUser.value) |
| | | //å¾å°äººåå表 |
| | | staffJoinListPage({staffState: 1}).then(res => { |
| | | staffOnJobListPage({staffState: 1}).then(res => { |
| | | //çéåºåcurrentUserååç人å |
| | | // let tableData = res.data.records |
| | | user.value = res.data.records.find(item => item.staffName === currentUser.value.userName) |
| | |
| | | const userRes = await getUserProfile(); |
| | | if (userRes.code === 200) { |
| | | currentUser.value = userRes.data; |
| | | const staffListRes = await staffJoinListPage({ staffState: 1 }); |
| | | const staffListRes = await staffOnJobListPage({ staffState: 1 }); |
| | | user.value = staffListRes.data.records.find(item => item.staffName === currentUser.value.userName); |
| | | // console.log("++++", user.value); |
| | | |
| | | Object.assign(joinForm, user.value); |
| | | joinForm.staffName = profileForm.name; |
| | | joinForm.phone = profileForm.phone; |
| | | joinForm.email = profileForm.email; |
| | | joinForm.adress = profileForm.adress; |
| | | console.log(joinForm) |
| | | // è°ç¨æ´æ°ä¸ªäººä¿¡æ¯çæ¥å£ |
| | | staffJoinUpdate(joinForm).then(res => { |
| | | updateStaffOnJob(user.value.id, joinForm).then(res => { |
| | | if (res.code === 200) { |
| | | ElMessage.success('个人信æ¯ä¿åæå'); |
| | | getProfile(); |
| | |
| | | </el-card> |
| | | |
| | | <!-- æ°å¢/ç¼è¾å¯¹è¯æ¡ --> |
| | | <el-dialog v-model="dialogVisible" :title="dialogType === 'add' ? 'æ°å¢ä»·æ ¼' : 'ç¼è¾ä»·æ ¼'" width="800px"> |
| | | <FormDialog v-model="dialogVisible" :title="dialogType === 'add' ? 'æ°å¢ä»·æ ¼' : 'ç¼è¾ä»·æ ¼'" :width="'800px'" :operation-type="dialogType" @close="dialogVisible = false" @confirm="handleSubmit" @cancel="dialogVisible = false"> |
| | | <el-form :model="formData" :rules="formRules" ref="formRef" label-width="120px"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | |
| | | <el-input v-model="formData.remark" type="textarea" :rows="3" placeholder="请è¾å
¥å¤æ³¨ä¿¡æ¯" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <el-button @click="dialogVisible = false">åæ¶</el-button> |
| | | <el-button type="primary" @click="handleSubmit" :loading="submitLoading">ç¡®å®</el-button> |
| | | </template> |
| | | </el-dialog> |
| | | </FormDialog> |
| | | |
| | | <!-- æ¹éææ£å¯¹è¯æ¡ --> |
| | | <el-dialog v-model="batchDiscountVisible" title="æ¹éè®¾ç½®ææ£" width="600px"> |
| | | <FormDialog v-model="batchDiscountVisible" title="æ¹éè®¾ç½®ææ£" :width="'600px'" @close="batchDiscountVisible = false" @confirm="handleBatchDiscount" @cancel="batchDiscountVisible = false"> |
| | | <el-form :model="batchDiscountForm" label-width="120px"> |
| | | <el-form-item label="ææ£ç±»å"> |
| | | <el-select v-model="batchDiscountForm.discountType" placeholder="è¯·éæ©ææ£ç±»å" style="width: 100%"> |
| | |
| | | </div> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <el-button @click="batchDiscountVisible = false">åæ¶</el-button> |
| | | <el-button type="primary" @click="handleBatchDiscount">ç¡®å®</el-button> |
| | | </template> |
| | | </el-dialog> |
| | | </FormDialog> |
| | | |
| | | <!-- ä»·æ ¼æ§å¶å¯¹è¯æ¡ --> |
| | | <el-dialog v-model="priceControlVisible" title="ä»·æ ¼æ§å¶è®¾ç½®" width="700px"> |
| | | <FormDialog v-model="priceControlVisible" title="ä»·æ ¼æ§å¶è®¾ç½®" :width="'700px'" @close="priceControlVisible = false" @confirm="handlePriceControl" @cancel="priceControlVisible = false"> |
| | | <el-form :model="priceControlForm" label-width="120px"> |
| | | <el-form-item label="é»è®¤æä½ä»·æ ¼"> |
| | | <el-input-number v-model="priceControlForm.defaultMinPrice" :min="0" :precision="2" style="width: 200px" /> |
| | |
| | | <el-input-number v-model="priceControlForm.changeThreshold" :min="0" :max="100" :precision="1" style="width: 200px" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <el-button @click="priceControlVisible = false">åæ¶</el-button> |
| | | <el-button type="primary" @click="handlePriceControl">ä¿å设置</el-button> |
| | | </template> |
| | | </el-dialog> |
| | | </FormDialog> |
| | | |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import FormDialog from '@/components/Dialog/FormDialog.vue'; |
| | | import {ref, reactive, computed, onMounted, getCurrentInstance} from 'vue' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | import { |
| | |
| | | /> |
| | | </el-card> |
| | | |
| | | <el-dialog v-model="dialogVisible" :title="dialogType === 'add' ? 'æ°å¢å°è´§' : 'ç¼è¾å°è´§'" width="600px"> |
| | | <FormDialog v-model="dialogVisible" :title="dialogType === 'add' ? 'æ°å¢å°è´§' : 'ç¼è¾å°è´§'" :width="'600px'" :operation-type="dialogType" @close="dialogVisible = false" @confirm="handleSubmit" @cancel="dialogVisible = false"> |
| | | <el-form :model="formData" label-width="120px"> |
| | | <el-form-item label="å°è´§åå·"> |
| | | <el-input v-model="formData.arrivalNo" placeholder="å°è´§åå·" /> |
| | |
| | | <el-input v-model="formData.remark" type="textarea" :rows="3" placeholder="请è¾å
¥å¤æ³¨ä¿¡æ¯" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <el-button @click="dialogVisible = false">åæ¶</el-button> |
| | | <el-button type="primary" @click="handleSubmit">ç¡®å®</el-button> |
| | | </template> |
| | | </el-dialog> |
| | | </FormDialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import FormDialog from '@/components/Dialog/FormDialog.vue'; |
| | | import { ref, reactive,onMounted } from 'vue' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | import {listPage,add,update,del} from "@/api/procurementManagement/arrivalManagement.js" |
| | |
| | | <template> |
| | | <el-dialog :title="modalOptions.title" v-model="visible" width="70%"> |
| | | <el-form |
| | | ref="formRef" |
| | | :model="form" |
| | | :rules="rules" |
| | | label-width="120px" |
| | | label-position="top" |
| | | > |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="éè´ååå·ï¼" prop="purchaseLedgerNo"> |
| | | <el-input v-model="form.purchaseLedgerNo" disabled /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="éå®ååå·ï¼" prop="salesContractNo"> |
| | | <el-input |
| | | v-model="form.salesContractNo" |
| | | placeholder="èªå¨å¡«å
" |
| | | clearable |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ä¾åºååç§°ï¼" prop="supplierName"> |
| | | <el-input |
| | | v-model="form.supplierName" |
| | | placeholder="èªå¨å¡«å
" |
| | | clearable |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="项ç®åç§°ï¼" prop="projectName"> |
| | | <el-input |
| | | v-model="form.projectName" |
| | | placeholder="èªå¨å¡«å
" |
| | | clearable |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å票å·ï¼" prop="invoiceNumber"> |
| | | <el-input |
| | | v-model="form.invoiceNumber" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å票éé¢(å
)ï¼" prop="invoiceAmount"> |
| | | <el-input-number :step="0.01" :min="0" style="width: 100%" |
| | | v-model="form.invoiceAmount" |
| | | placeholder="èªå¨å¡«å
" |
| | | clearable |
| | | :disabled="true" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å½å
¥äººï¼" prop="issUer"> |
| | | <el-input |
| | | v-model="form.issUer" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å¼ç¥¨æ¥æï¼" prop="entryDate"> |
| | | <el-date-picker |
| | | style="width: 100%" |
| | | v-model="form.entryDate" |
| | | type="date" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ä¸ä¼ éä»¶"> |
| | | <FileUpload |
| | | :showTip="false" |
| | | accept="*" |
| | | :autoUpload="true" |
| | | :action="action" |
| | | :headers="{ |
| | | <el-dialog :title="modalOptions.title" v-model="visible" width="70%" draggable> |
| | | <el-form |
| | | ref="formRef" |
| | | :model="form" |
| | | :rules="rules" |
| | | label-width="120px" |
| | | label-position="top" |
| | | > |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="éè´ååå·ï¼" prop="purchaseLedgerNo"> |
| | | <el-input v-model="form.purchaseLedgerNo" disabled placeholder="å¤ååæ¹éå¤çï¼å
·ä½ååå·è§äº§åå表ï¼" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="éå®ååå·ï¼" prop="salesContractNo"> |
| | | <el-input |
| | | v-model="form.salesContractNo" |
| | | placeholder="èªå¨å¡«å
" |
| | | clearable |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ä¾åºååç§°ï¼" prop="supplierName"> |
| | | <el-input |
| | | v-model="form.supplierName" |
| | | placeholder="èªå¨å¡«å
" |
| | | clearable |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <!-- <el-col :span="12">--> |
| | | <!-- <el-form-item label="项ç®åç§°ï¼" prop="projectName">--> |
| | | <!-- <el-input--> |
| | | <!-- v-model="form.projectName"--> |
| | | <!-- placeholder="èªå¨å¡«å
"--> |
| | | <!-- clearable--> |
| | | <!-- disabled--> |
| | | <!-- />--> |
| | | <!-- </el-form-item>--> |
| | | <!-- </el-col>--> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å票å·ï¼" prop="invoiceNumber"> |
| | | <el-input |
| | | v-model="form.invoiceNumber" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å票éé¢(å
)ï¼" prop="invoiceAmount"> |
| | | <el-input-number :step="0.01" :min="0" style="width: 100%" |
| | | v-model="form.invoiceAmount" |
| | | placeholder="请è¾å
¥å票éé¢" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å½å
¥äººï¼" prop="issUer"> |
| | | <el-input |
| | | v-model="form.issUer" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å¼ç¥¨æ¥æï¼" prop="entryDate"> |
| | | <el-date-picker |
| | | style="width: 100%" |
| | | v-model="form.entryDate" |
| | | type="date" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å½å
¥æ¥æï¼" prop="enterDate"> |
| | | <el-date-picker |
| | | style="width: 100%" |
| | | v-model="form.enterDate" |
| | | type="date" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ä¸ä¼ éä»¶"> |
| | | <FileUpload |
| | | :showTip="false" |
| | | accept="*" |
| | | :autoUpload="true" |
| | | :action="action" |
| | | :headers="{ |
| | | Authorization: 'Bearer ' + getToken(), |
| | | }" |
| | | :limit="10" |
| | | @success="uploadSuccess" |
| | | @remove="removeFile" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å½å
¥æ¥æï¼" prop="enterDate"> |
| | | <el-date-picker |
| | | style="width: 100%" |
| | | v-model="form.enterDate" |
| | | type="date" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-form-item label="产åä¿¡æ¯ï¼"> </el-form-item> |
| | | <PIMTable |
| | | rowKey="id" |
| | | :column="columns" |
| | | :tableData="form.productData" |
| | | :summaryMethod="summarizeChildrenTable" |
| | | :isShowSummary="true" |
| | | height="auto" |
| | | > |
| | | <template #ticketsNumRef="{ row }"> |
| | | <el-input-number |
| | | v-model="row.ticketsNum" |
| | | placeholder="请è¾å
¥" |
| | | :min="0" |
| | | :step="0.1" |
| | | :precision="2" |
| | | clearable |
| | | style="width: 100%" |
| | | @change="invoiceNumBlur(row)" |
| | | /> |
| | | </template> |
| | | <template #ticketsAmountRef="{ row }"> |
| | | <el-input-number |
| | | v-model="row.ticketsAmount" |
| | | placeholder="请è¾å
¥" |
| | | :min="0" |
| | | :precision="2" |
| | | :step="0.1" |
| | | clearable |
| | | style="width: 100%" |
| | | @change="invoiceAmountBlur(row)" |
| | | /> |
| | | </template> |
| | | </PIMTable> |
| | | </el-form> |
| | | <template #footer> |
| | | :limit="10" |
| | | @success="uploadSuccess" |
| | | @remove="removeFile" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | |
| | | </el-row> |
| | | <el-form-item label="产åä¿¡æ¯ï¼"> </el-form-item> |
| | | <el-table |
| | | :data="form.productData" |
| | | border |
| | | show-summary |
| | | :summary-method="summarizeChildrenTable" |
| | | > |
| | | <el-table-column align="center" label="åºå·" type="index" width="60" /> |
| | | <el-table-column label="æå±åå" prop="purchaseLedgerNo" width="200"> |
| | | <template #default="{ row }"> |
| | | <el-tag type="primary">{{ row.purchaseLedgerNo }}</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="产å大类" prop="productCategory" /> |
| | | <el-table-column label="è§æ ¼åå·" prop="specificationModel" width="150" /> |
| | | <el-table-column label="åä½" prop="unit" width="70" /> |
| | | <el-table-column label="æ°é" prop="quantity" width="70" /> |
| | | <el-table-column label="ç¨ç(%)" prop="taxRate" width="80" /> |
| | | <el-table-column |
| | | label="å«ç¨åä»·(å
)" |
| | | prop="taxInclusiveUnitPrice" |
| | | :formatter="formattedNumber" |
| | | /> |
| | | <el-table-column |
| | | label="å«ç¨æ»ä»·(å
)" |
| | | prop="taxInclusiveTotalPrice" |
| | | :formatter="formattedNumber" |
| | | /> |
| | | <el-table-column |
| | | label="ä¸å«ç¨æ»ä»·(å
)" |
| | | prop="taxExclusiveTotalPrice" |
| | | :formatter="formattedNumber" |
| | | /> |
| | | <el-table-column label="æ¬æ¬¡å¼ç¥¨æ°" prop="ticketsNum" width="180"> |
| | | <template #default="scope"> |
| | | <el-input-number :step="0.1" :min="0" style="width: 100%" |
| | | :precision="2" |
| | | v-model="scope.row.ticketsNum" |
| | | @change="invoiceNumBlur(scope.row)" |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="æ¬æ¬¡å¼ç¥¨éé¢(å
)" |
| | | prop="ticketsAmount" |
| | | width="180" |
| | | > |
| | | <template #default="scope"> |
| | | <el-input-number :step="0.01" :min="0" style="width: 100%" |
| | | :precision="2" |
| | | v-model="scope.row.ticketsAmount" |
| | | @change="invoiceAmountBlur(scope.row)" |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="æªæ¥ç¥¨æ°" |
| | | prop="futureTickets" |
| | | :formatter="formattedNumber" |
| | | /> |
| | | <el-table-column |
| | | label="æ¬æ¬¡æ¥ç¥¨éé¢(å
)" |
| | | prop="ticketsAmount" |
| | | :formatter="formattedNumber" |
| | | /> |
| | | <el-table-column |
| | | label="æªæ¥ç¥¨æ°" |
| | | prop="futureTickets" |
| | | :formatter="formattedNumber" |
| | | /> |
| | | <el-table-column |
| | | label="æªæ¥ç¥¨éé¢(å
)" |
| | | prop="futureTicketsAmount" |
| | | :formatter="formattedNumber" |
| | | /> |
| | | </el-table> |
| | | </el-form> |
| | | <template #footer> |
| | | <el-button type="primary" :loading="modalLoading" @click="submitForm"> |
| | | {{ modalOptions.confirmText }} |
| | | 确认 |
| | | </el-button> |
| | | <el-button @click="closeModal">{{ modalOptions.cancelText }}</el-button> |
| | | </template> |
| | | </el-dialog> |
| | | <el-button @click="closeModal">åæ¶</el-button> |
| | | </template> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | |
| | | import useFormData from "@/hooks/useFormData"; |
| | | import FileUpload from "@/components/Upload/FileUpload.vue"; |
| | | import { |
| | | getPurchaseNoById, |
| | | getInfo, |
| | | addOrUpdateRegistration, |
| | | getPurchaseNoById, |
| | | getInfo, |
| | | addOrUpdateRegistration, |
| | | } from "@/api/procurementManagement/invoiceEntry.js"; |
| | | import { getPurchaseById } from "@/api/procurementManagement/procurementLedger.js"; |
| | | import { getToken } from "@/utils/auth"; |
| | |
| | | import dayjs from "dayjs"; |
| | | |
| | | defineOptions({ |
| | | name: "æ¥ç¥¨ç»è®°æ¨¡ææ¡", |
| | | name: "æ¥ç¥¨ç»è®°æ¨¡ææ¡", |
| | | }); |
| | | |
| | | const userStore = useUserStore(); |
| | |
| | | const formRef = ref(); |
| | | const { proxy } = getCurrentInstance(); |
| | | const { form } = useFormData({ |
| | | purchaseLedgerNo: undefined, // éè´ååå· |
| | | salesContractNo: undefined, // éå®ååå· |
| | | supplierName: undefined, // ä¾åºååç§° |
| | | projectName: undefined, // 项ç®åç§° |
| | | invoiceNumber: undefined, // åç¥¨å· |
| | | invoiceAmount: undefined, // å票éé¢(å
) |
| | | issUerId: userStore.id, // å½å
¥äºº |
| | | issUer: userStore.nickName, // å½å
¥äºº |
| | | entryDate: undefined, // å¼ç¥¨æ¥æ |
| | | salesContractNoId: undefined, // å¼ç¥¨æ¥æ |
| | | enterDate: dayjs().format("YYYY-MM-DD"), |
| | | productData: [], // è¡¨æ ¼ |
| | | tempFileIds: [], // æä»¶ |
| | | purchaseLedgerNo: undefined, // éè´ååå· |
| | | salesContractNo: undefined, // éå®ååå· |
| | | supplierName: undefined, // ä¾åºååç§° |
| | | projectName: undefined, // 项ç®åç§° |
| | | invoiceNumber: undefined, // åç¥¨å· |
| | | invoiceAmount: undefined, // å票éé¢(å
) |
| | | issUerId: userStore.id, // å½å
¥äºº |
| | | issUer: userStore.nickName, // å½å
¥äºº |
| | | entryDate: undefined, // å¼ç¥¨æ¥æ |
| | | salesContractNoId: undefined, // å¼ç¥¨æ¥æ |
| | | enterDate: dayjs().format("YYYY-MM-DD"), |
| | | productData: [], // è¡¨æ ¼ |
| | | tempFileIds: [], // æä»¶ |
| | | }); |
| | | |
| | | const selectedContracts = ref([]); // åå¨éä¸çååæ°æ® |
| | | |
| | | const rules = ref({ |
| | | invoiceNumber: [ |
| | | { required: true, message: "请è¾å
¥å票å·", trigger: "blur" }, |
| | | { type: "string" }, |
| | | ], |
| | | invoiceAmount: [ |
| | | { required: true, message: "请è¾å
¥å票éé¢", trigger: "blur" }, |
| | | ], |
| | | entryDate: [{ required: true, message: "è¯·éæ©å¼ç¥¨æ¥æ", trigger: "change" }], |
| | | enterDate: [{ required: true, message: "è¯·éæ©å½å
¥æ¥æ", trigger: "change" }], |
| | | invoiceNumber: [ |
| | | { required: true, message: "请è¾å
¥å票å·", trigger: "blur" }, |
| | | { type: "string" }, |
| | | ], |
| | | invoiceAmount: [ |
| | | { required: true, message: "请è¾å
¥å票éé¢", trigger: "blur" }, |
| | | ], |
| | | entryDate: [{ required: true, message: "è¯·éæ©å¼ç¥¨æ¥æ", trigger: "change" }], |
| | | enterDate: [{ required: true, message: "è¯·éæ©å½å
¥æ¥æ", trigger: "change" }], |
| | | }); |
| | | |
| | | const { |
| | | id, |
| | | visible, |
| | | loading: modalLoading, |
| | | openModal, |
| | | modalOptions, |
| | | handleConfirm, |
| | | closeModal, |
| | | id, |
| | | visible, |
| | | loading: modalLoading, |
| | | openModal, |
| | | modalOptions, |
| | | handleConfirm, |
| | | closeModal, |
| | | } = useModal({ |
| | | title: "æ¥ç¥¨ç»è®°", |
| | | title: "æ¥ç¥¨ç»è®°", |
| | | }); |
| | | |
| | | const emit = defineEmits(['refreshList']); |
| | | |
| | | const columns = [ |
| | | { |
| | | label: "产å大类", |
| | | prop: "productCategory", |
| | | { |
| | | label: "产å大类", |
| | | prop: "productCategory", |
| | | width: 120, |
| | | }, |
| | | { |
| | | label: "è§æ ¼åå·", |
| | | prop: "specificationModel", |
| | | }, |
| | | { |
| | | label: "è§æ ¼åå·", |
| | | prop: "specificationModel", |
| | | width: 120, |
| | | }, |
| | | { |
| | | label: "åä½", |
| | | prop: "unit", |
| | | width: 80, |
| | | }, |
| | | { |
| | | label: "æ°é", |
| | | prop: "quantity", |
| | | width: 80, |
| | | }, |
| | | { |
| | | label: "ç¨ç(%)", |
| | | prop: "taxRate", |
| | | width: 80, |
| | | }, |
| | | { |
| | | label: "å½å
¥æ¥æ", |
| | | prop: "registerDate", |
| | | width: 120, |
| | | }, |
| | | { |
| | | label: "å«ç¨åä»·(å
)", |
| | | prop: "taxInclusiveUnitPrice", |
| | | width: 150, |
| | | formatData: (val) => { |
| | | return val ? parseFloat(val).toFixed(2) : 0; |
| | | }, |
| | | }, |
| | | { |
| | | label: "å«ç¨æ»ä»·(å
)", |
| | | prop: "taxInclusiveTotalPrice", |
| | | width: 150, |
| | | formatData: (val) => { |
| | | return parseFloat(val).toFixed(2) ?? 0; |
| | | }, |
| | | }, |
| | | { |
| | | label: "ä¸å«ç¨æ»ä»·(å
)", |
| | | prop: "taxExclusiveTotalPrice", |
| | | width: 150, |
| | | formatData: (val) => { |
| | | return parseFloat(val).toFixed(2) ?? 0; |
| | | }, |
| | | }, |
| | | { |
| | | label: "æ¬æ¬¡æ¥ç¥¨æ°", |
| | | prop: "ticketsNum", |
| | | dataType: "slot", |
| | | slot: "ticketsNumRef", |
| | | width: 180, |
| | | align: "center", |
| | | }, |
| | | { |
| | | label: "æ¬æ¬¡æ¥ç¥¨éé¢(å
)", |
| | | prop: "ticketsAmount", |
| | | dataType: "slot", |
| | | slot: "ticketsAmountRef", |
| | | width: 180, |
| | | align: "center", |
| | | }, |
| | | { |
| | | label: "æªæ¥ç¥¨æ°", |
| | | prop: "futureTickets", |
| | | }, |
| | | { |
| | | label: "åä½", |
| | | prop: "unit", |
| | | width: 80, |
| | | }, |
| | | { |
| | | label: "æ°é", |
| | | prop: "quantity", |
| | | width: 80, |
| | | }, |
| | | { |
| | | label: "ç¨ç(%)", |
| | | prop: "taxRate", |
| | | width: 80, |
| | | }, |
| | | { |
| | | label: "å½å
¥æ¥æ", |
| | | prop: "registerDate", |
| | | width: 120, |
| | | }, |
| | | { |
| | | label: "å«ç¨åä»·(å
)", |
| | | prop: "taxInclusiveUnitPrice", |
| | | width: 150, |
| | | formatData: (val) => { |
| | | return val ? parseFloat(val).toFixed(2) : 0; |
| | | }, |
| | | }, |
| | | { |
| | | label: "å«ç¨æ»ä»·(å
)", |
| | | prop: "taxInclusiveTotalPrice", |
| | | width: 150, |
| | | formatData: (val) => { |
| | | return parseFloat(val).toFixed(2) ?? 0; |
| | | }, |
| | | }, |
| | | { |
| | | label: "ä¸å«ç¨æ»ä»·(å
)", |
| | | prop: "taxExclusiveTotalPrice", |
| | | width: 150, |
| | | formatData: (val) => { |
| | | return parseFloat(val).toFixed(2) ?? 0; |
| | | }, |
| | | }, |
| | | { |
| | | label: "æ¬æ¬¡æ¥ç¥¨æ°", |
| | | prop: "ticketsNum", |
| | | dataType: "slot", |
| | | slot: "ticketsNumRef", |
| | | width: 180, |
| | | align: "center", |
| | | }, |
| | | { |
| | | label: "æ¬æ¬¡æ¥ç¥¨éé¢(å
)", |
| | | prop: "ticketsAmount", |
| | | dataType: "slot", |
| | | slot: "ticketsAmountRef", |
| | | width: 180, |
| | | align: "center", |
| | | }, |
| | | { |
| | | label: "æªæ¥ç¥¨æ°", |
| | | prop: "futureTickets", |
| | | width: 100, |
| | | }, |
| | | { |
| | | label: "æªæ¥ç¥¨éé¢(å
)", |
| | | prop: "futureTicketsAmount", |
| | | }, |
| | | { |
| | | label: "æªæ¥ç¥¨éé¢(å
)", |
| | | prop: "futureTicketsAmount", |
| | | width: 200, |
| | | }, |
| | | }, |
| | | ]; |
| | | |
| | | const getTableData = async (type, id) => { |
| | | if (type == "add") { |
| | | const { data } = await getPurchaseNoById({ id }); |
| | | form.purchaseLedgerNo = data.purchaseContractNumber; |
| | | form.invoiceAmount = data.invoiceAmount; |
| | | form.invoiceNumber = data.invoiceNumber; |
| | | form.entryDate = data.entryDate; |
| | | form.salesContractNoId = data.salesContractNoId; |
| | | |
| | | const { data: infoData } = await getInfo({ id }); |
| | | form.salesContractNo = infoData.salesContractNo; |
| | | form.projectName = infoData.projectName; |
| | | form.supplierName = infoData.supplierName; |
| | | form.productData = infoData.productData; |
| | | } else if (type == "edit") { |
| | | const data = await getPurchaseById({ id, type: 2 }); |
| | | form.purchaseLedgerNo = data.purchaseContractNumber; |
| | | form.invoiceAmount = data.invoiceAmount; |
| | | form.invoiceNumber = data.invoiceNumber; |
| | | form.salesContractNo = data.salesContractNo; |
| | | form.projectName = data.projectName; |
| | | form.supplierName = data.supplierName; |
| | | form.entryDate = data.entryDate; |
| | | form.productData = data.productData; |
| | | } |
| | | const formattedNumber = (row, column, cellValue) => { |
| | | if (cellValue == 0) { |
| | | return parseFloat(cellValue).toFixed(2); |
| | | } |
| | | if (cellValue) { |
| | | return parseFloat(cellValue).toFixed(2); |
| | | } else { |
| | | return cellValue; |
| | | } |
| | | }; |
| | | const getTableData = async (type, selectedRows) => { |
| | | if (type == "add") { |
| | | // æ£æ¥ææéæ©çå忝å¦å
·æç¸åçä¾åºååç§° |
| | | const firstRow = selectedRows[0]; |
| | | const isSameSupplier = selectedRows.every(row => |
| | | row.supplierName === firstRow.supplierName |
| | | ); |
| | | |
| | | if (!isSameSupplier) { |
| | | proxy.$modal.msgError("è¯·éæ©ç¸åä¾åºååç§°çåå"); |
| | | return; |
| | | } |
| | | |
| | | // å
许ä¸åçéè´ååå·æ¹éå¤çï¼æ 鿣æ¥éå¤ |
| | | |
| | | // æ¸
ç©ºè¡¨åæ°æ® |
| | | Object.keys(form).forEach(key => { |
| | | if (key !== 'productData') { |
| | | form[key] = undefined; |
| | | } |
| | | }); |
| | | form.productData = []; |
| | | |
| | | // å è½½ææéä¸ååçäº§åæ°æ® |
| | | const promises = selectedRows.map(row => |
| | | getInfo({ id: row.id }) |
| | | ); |
| | | |
| | | Promise.all(promises).then(results => { |
| | | // åå¹¶ææååçäº§åæ°æ®ï¼å¹¶ä¸ºæ¯ä¸ªäº§åæ·»å 对åºçååä¿¡æ¯ |
| | | const allProductData = []; |
| | | results.forEach((result, index) => { |
| | | const contract = selectedRows[index]; |
| | | const contractId = contract.id; |
| | | if (result.data && result.data.productData) { |
| | | result.data.productData.forEach(item => { |
| | | allProductData.push({ |
| | | ...item, |
| | | id: contractId, // æç¡®è®¾ç½®ååID |
| | | purchaseLedgerNo: contract.purchaseContractNumber, // æ·»å éè´ååå· |
| | | supplierName: contract.supplierName, // æ·»å ä¾åºååç§° |
| | | projectName: contract.projectName // æ·»å 项ç®åç§° |
| | | }); |
| | | }); |
| | | } |
| | | }); |
| | | |
| | | // è®¾ç½®è¡¨åæ°æ®ï¼ä½¿ç¨ç¬¬ä¸ä¸ªååçåºæ¬ä¿¡æ¯ï¼éè´ååå·çç©ºï¼ |
| | | form.purchaseLedgerNo = ""; // éè´ååå·ç空ï¼å 为ä¼å¨äº§åè¡¨æ ¼ä¸å嫿¾ç¤º |
| | | form.invoiceNumber = ""; |
| | | form.entryDate = dayjs().format("YYYY-MM-DD"); |
| | | form.enterDate = dayjs().format("YYYY-MM-DD"); |
| | | form.salesContractNo = results[0].data.salesContractNo; |
| | | form.projectName = results[0].data.projectName; |
| | | form.supplierName = results[0].data.supplierName; |
| | | // ä¿çå½å
¥äººä¿¡æ¯ |
| | | form.issUerId = userStore.id; |
| | | form.issUer = userStore.nickName; |
| | | |
| | | // è®¾ç½®äº§åæ°æ®ï¼å¹¶åå§åå¼ç¥¨æ°éåéé¢ |
| | | allProductData.forEach(item => { |
| | | // æ¬æ¬¡å¼ç¥¨æ°é»è®¤ä¸ºæ»æ°é |
| | | item.ticketsNum = Number(item.quantity || 0); |
| | | // æ¬æ¬¡å¼ç¥¨éé¢é»è®¤ä¸ºå«ç¨æ»ä»· |
| | | item.ticketsAmount = Number(item.taxInclusiveTotalPrice || 0); |
| | | // ä¿ååå§æªæ¥ç¥¨æ°åéé¢ï¼ç¨äºè®¡ç®ï¼ |
| | | item.tempFutureTickets = Number(item.quantity || 0); |
| | | item.tempFutureTicketsAmount = Number(item.taxInclusiveTotalPrice || 0); |
| | | // æªæ¥ç¥¨æ°åéé¢åå§ä¸º0ï¼å 为å
¨é¨å¼ç¥¨ï¼ |
| | | item.futureTickets = 0; |
| | | item.futureTicketsAmount = 0; |
| | | }); |
| | | |
| | | form.productData = allProductData; |
| | | |
| | | // 计ç®å票éé¢ï¼ææäº§åçå«ç¨æ»ä»·ä¹å |
| | | const totalAmount = allProductData.reduce((sum, item) => { |
| | | return sum + (Number(item.taxInclusiveTotalPrice) || 0); |
| | | }, 0); |
| | | form.invoiceAmount = totalAmount.toFixed(2); |
| | | |
| | | // åå¨éä¸çååæ°æ® |
| | | selectedContracts.value = selectedRows; |
| | | }); |
| | | } else if (type == "edit") { |
| | | const id = Array.isArray(selectedRows) ? selectedRows[0].id : selectedRows; |
| | | const data = await getPurchaseById({ id, type: 2 }); |
| | | form.purchaseLedgerNo = data.purchaseContractNumber; |
| | | form.invoiceAmount = data.invoiceAmount; |
| | | form.invoiceNumber = data.invoiceNumber; |
| | | form.salesContractNo = data.salesContractNo; |
| | | form.projectName = data.projectName; |
| | | form.supplierName = data.supplierName; |
| | | form.entryDate = data.entryDate; |
| | | form.productData = data.productData; |
| | | } |
| | | }; |
| | | // å表åè®¡æ¹æ³ |
| | | const summarizeChildrenTable = (param) => { |
| | |
| | | }; |
| | | //æ¬æ¬¡æ¥ç¥¨æ°å¤±ç¦æä½ |
| | | const invoiceNumBlur = (row) => { |
| | | if (!row.ticketsNum || row.ticketsNum === "") { |
| | | row.ticketsNum = 0; |
| | | } |
| | | if (Number(row.ticketsNum) > Number(row.tempFutureTickets)) { |
| | | proxy.$modal.msgWarning("æ¬æ¬¡å¼ç¥¨æ°ä¸å¾å¤§äºæªå¼ç¥¨æ°"); |
| | | row.ticketsNum = 0; |
| | | return; |
| | | } |
| | | // è®¡ç®æ¬æ¬¡æ¥ç¥¨éé¢ |
| | | row.ticketsAmount = (row.ticketsNum * row.taxInclusiveUnitPrice).toFixed(2) |
| | | // è®¡ç®æªæ¥ç¥¨æ° |
| | | row.futureTickets = (row.tempFutureTickets - row.ticketsNum).toFixed(2) |
| | | // è®¡ç®æªæ¥ç¥¨éé¢ |
| | | row.futureTicketsAmount = (row.tempFutureTicketsAmount - row.ticketsAmount).toFixed(2) |
| | | calculateinvoiceAmount(); |
| | | if (!row.ticketsNum || row.ticketsNum === "") { |
| | | row.ticketsNum = 0; |
| | | } |
| | | if (Number(row.ticketsNum) > Number(row.tempFutureTickets)) { |
| | | proxy.$modal.msgWarning("æ¬æ¬¡å¼ç¥¨æ°ä¸å¾å¤§äºæªå¼ç¥¨æ°"); |
| | | row.ticketsNum = 0; |
| | | return; |
| | | } |
| | | // è®¡ç®æ¬æ¬¡æ¥ç¥¨éé¢ |
| | | row.ticketsAmount = (row.ticketsNum * row.taxInclusiveUnitPrice).toFixed(2) |
| | | // è®¡ç®æªæ¥ç¥¨æ° |
| | | row.futureTickets = (row.tempFutureTickets - row.ticketsNum).toFixed(2) |
| | | // è®¡ç®æªæ¥ç¥¨éé¢ |
| | | row.futureTicketsAmount = (row.tempFutureTicketsAmount - row.ticketsAmount).toFixed(2) |
| | | calculateinvoiceAmount(); |
| | | }; |
| | | |
| | | // æ¬æ¬¡æ¥ç¥¨éé¢å¤±ç¦æä½ |
| | | const invoiceAmountBlur = (row) => { |
| | | if (!row.ticketsAmount) { |
| | | row.ticketsAmount = 0; |
| | | } |
| | | // è®¡ç®æ¯å¦è¶
è¿æ¥ç¥¨æ»éé¢ |
| | | if (row.ticketsAmount > row.tempFutureTicketsAmount) { |
| | | proxy.$modal.msgWarning("æ¬æ¬¡æ¥ç¥¨éé¢ä¸å¾å¤§äºæªæ¥ç¥¨éé¢"); |
| | | row.ticketsAmount = 0; |
| | | } |
| | | // è®¡ç®æ¬æ¬¡æ¥ç¥¨æ° |
| | | row.ticketsNum = Number( |
| | | (row.ticketsAmount / row.taxInclusiveUnitPrice).toFixed(2) |
| | | ); |
| | | // è®¡ç®æªæ¥ç¥¨æ° |
| | | row.futureTickets = (row.tempFutureTickets - row.ticketsNum).toFixed(2) |
| | | // è®¡ç®æªæ¥ç¥¨éé¢ |
| | | row.futureTicketsAmount = (row.tempFutureTicketsAmount - row.ticketsAmount).toFixed(2) |
| | | calculateinvoiceAmount(); |
| | | if (!row.ticketsAmount) { |
| | | row.ticketsAmount = 0; |
| | | } |
| | | // è®¡ç®æ¯å¦è¶
è¿æ¥ç¥¨æ»éé¢ |
| | | if (row.ticketsAmount > row.tempFutureTicketsAmount) { |
| | | proxy.$modal.msgWarning("æ¬æ¬¡æ¥ç¥¨éé¢ä¸å¾å¤§äºæªæ¥ç¥¨éé¢"); |
| | | row.ticketsAmount = 0; |
| | | } |
| | | // è®¡ç®æ¬æ¬¡æ¥ç¥¨æ° |
| | | row.ticketsNum = Number( |
| | | (row.ticketsAmount / row.taxInclusiveUnitPrice).toFixed(2) |
| | | ); |
| | | // è®¡ç®æªæ¥ç¥¨æ° |
| | | row.futureTickets = (row.tempFutureTickets - row.ticketsNum).toFixed(2) |
| | | // è®¡ç®æªæ¥ç¥¨éé¢ |
| | | row.futureTicketsAmount = (row.tempFutureTicketsAmount - row.ticketsAmount).toFixed(2) |
| | | calculateinvoiceAmount(); |
| | | }; |
| | | |
| | | const calculateinvoiceAmount = () => { |
| | | let invoiceAmountTotal = 0; |
| | | form.productData.forEach((item) => { |
| | | if (item.ticketsAmount) { |
| | | invoiceAmountTotal += Number(item.ticketsAmount); |
| | | } |
| | | }); |
| | | form.invoiceAmount = invoiceAmountTotal.toFixed(2); |
| | | let invoiceAmountTotal = 0; |
| | | form.productData.forEach((item) => { |
| | | if (item.ticketsAmount) { |
| | | invoiceAmountTotal += Number(item.ticketsAmount); |
| | | } |
| | | }); |
| | | form.invoiceAmount = invoiceAmountTotal.toFixed(2); |
| | | }; |
| | | |
| | | const open = (type, eid) => { |
| | | openModal(); |
| | | getTableData(type, eid); |
| | | id.value = eid; |
| | | const open = async (type, selectedRows) => { |
| | | visible.value = true; |
| | | |
| | | // å¦ææ¯æ¹éæä½ï¼è®¾ç½®æ é¢ |
| | | if (Array.isArray(selectedRows) && selectedRows.length > 1) { |
| | | modalOptions.title = `æ¹éæ°å¢ (${selectedRows.length}æ¡)`; |
| | | } else { |
| | | modalOptions.title = type === "add" ? "æ°å¢" : "ç¼è¾"; |
| | | } |
| | | |
| | | // 妿æ¯å个æä½ï¼è·åid |
| | | if (!Array.isArray(selectedRows) || selectedRows.length === 1) { |
| | | const idValue = Array.isArray(selectedRows) ? selectedRows[0].id : selectedRows; |
| | | id.value = idValue; |
| | | } |
| | | |
| | | await getTableData(type, selectedRows); |
| | | }; |
| | | |
| | | const uploadSuccess = (response) => { |
| | | form.tempFileIds.push(response.data.tempId); |
| | | console.log(form); |
| | | form.tempFileIds.push(response.data.tempId); |
| | | console.log(form); |
| | | }; |
| | | |
| | | const removeFile = (file) => { |
| | | const { tempId } = file.response.data; |
| | | form.tempFileIds = form.tempFileIds.filter((item) => item !== tempId); |
| | | const { tempId } = file.response.data; |
| | | form.tempFileIds = form.tempFileIds.filter((item) => item !== tempId); |
| | | }; |
| | | |
| | | const closeAndRefresh = () => { |
| | | closeModal(); |
| | | emit('refreshList'); |
| | | closeModal(); |
| | | emit('refreshList'); |
| | | }; |
| | | |
| | | const submitForm = () => { |
| | | formRef.value.validate(async (valid, fields) => { |
| | | if (valid) { |
| | | // modalLoading.value = true; |
| | | const { code } = await addOrUpdateRegistration({ |
| | | purchaseLedgerId: id.value, |
| | | purchaseContractNumber: form.purchaseLedgerNo, |
| | | invoiceNumber: form.invoiceNumber, |
| | | invoiceAmount: form.invoiceAmount, |
| | | salesContractNo: form.salesContractNo, |
| | | projectName: form.projectName, |
| | | productData: form.productData, |
| | | issueDate: form.entryDate, |
| | | issUerId: form.issUerId, // å½å
¥äººid |
| | | issUer: form.issUer, // å½å
¥äºº |
| | | salesContractNoId: form.salesContractNoId, |
| | | supplierName: form.supplierName, |
| | | tempFileIds: form.tempFileIds, |
| | | enterDate: form.enterDate, |
| | | type: 4, |
| | | }); |
| | | modalLoading.value = false; |
| | | if (code == 200) { |
| | | closeAndRefresh(); |
| | | } |
| | | } else { |
| | | modalLoading.value = false; |
| | | } |
| | | }); |
| | | proxy.$refs["formRef"].validate((valid) => { |
| | | if (valid) { |
| | | // å¦ææ¯æ¹éæä½ï¼å°ææååçæ°æ®æ¾å¨ä¸ä¸ªæ°ç»éï¼åªè°ç¨ä¸æ¬¡æ¥å£ |
| | | if (selectedContracts.value.length > 1) { |
| | | // å建å
嫿æååæ°æ®çæ°ç» |
| | | const batchData = selectedContracts.value.map(contract => { |
| | | // çéåºå±äºå½åååçäº§åæ°æ® |
| | | const contractProductData = form.productData.filter(item => |
| | | item.id === contract.id |
| | | ); |
| | | |
| | | // 为æ¯ä¸ªéè´ååå建ç¬ç«ç对象 |
| | | return { |
| | | // åºç¡è¡¨åæ°æ® |
| | | invoiceNumber: form.invoiceNumber, |
| | | invoiceAmount: form.invoiceAmount, |
| | | entryDate: form.entryDate, |
| | | enterDate: form.enterDate, |
| | | issUerId: form.issUerId, // å½å
¥äººid |
| | | issUer: form.issUer, // å½å
¥äºº |
| | | tempFileIds: form.tempFileIds, |
| | | |
| | | // ååå®é
ä¿¡æ¯ |
| | | purchaseLedgerId: contract.id, // 使ç¨idä½ä¸ºå段åï¼å¼ä¸ºpurchaseLedgerId |
| | | purchaseContractNumber: contract.purchaseContractNumber, // 使ç¨å®é
çéè´ååå· |
| | | salesContractNo: contract.salesContractNo, // 使ç¨å®é
çéå®ååå· |
| | | supplierName: contract.supplierName, // 使ç¨å®é
çä¾åºååç§° |
| | | projectName: contract.projectName, // 使ç¨å®é
ç项ç®åç§° |
| | | |
| | | // äº§åæ°æ® |
| | | productData: proxy.HaveJson(contractProductData), |
| | | |
| | | // æ¹éæ è¯ |
| | | isBatch: true, |
| | | type: 4 |
| | | }; |
| | | }); |
| | | |
| | | // åªè°ç¨ä¸æ¬¡æ¥å£ï¼ä¼ éå
嫿æååæ°æ®çæ°ç» |
| | | modalLoading.value = true; |
| | | addOrUpdateRegistration(batchData).then((res) => { |
| | | modalLoading.value = false; |
| | | if (res.code === 200) { |
| | | proxy.$modal.msgSuccess("æ¹éç»è®°æå"); |
| | | closeAndRefresh(); |
| | | } |
| | | }).catch(() => { |
| | | modalLoading.value = false; |
| | | proxy.$modal.msgError("æ¹éç»è®°å¤±è´¥"); |
| | | }); |
| | | } else { |
| | | // å个ååæäº¤é»è¾ - 以æ°ç»æ ¼å¼ä¼ é |
| | | const singleContract = selectedContracts.value[0]; |
| | | const singleFormArray = [{ |
| | | // åºç¡è¡¨åæ°æ® |
| | | invoiceNumber: form.invoiceNumber, |
| | | invoiceAmount: form.invoiceAmount, |
| | | entryDate: form.entryDate, |
| | | enterDate: form.enterDate, |
| | | issUerId: form.issUerId, // å½å
¥äººid |
| | | issUer: form.issUer, // å½å
¥äºº |
| | | tempFileIds: form.tempFileIds, |
| | | |
| | | // ååå®é
ä¿¡æ¯ |
| | | purchaseLedgerId: singleContract.id, // 使ç¨idä½ä¸ºå段åï¼å¼ä¸ºpurchaseLedgerId |
| | | purchaseContractNumber: singleContract.purchaseContractNumber, // 使ç¨å®é
çéè´ååå· |
| | | salesContractNo: singleContract.salesContractNo, // 使ç¨å®é
çéå®ååå· |
| | | supplierName: singleContract.supplierName, // 使ç¨å®é
çä¾åºååç§° |
| | | projectName: singleContract.projectName, // 使ç¨å®é
ç项ç®åç§° |
| | | |
| | | // äº§åæ°æ® |
| | | productData: proxy.HaveJson(form.productData), |
| | | |
| | | // æ¹éæ è¯ |
| | | isBatch: false, |
| | | type: 4 |
| | | }]; |
| | | |
| | | modalLoading.value = true; |
| | | addOrUpdateRegistration(singleFormArray).then((res) => { |
| | | modalLoading.value = false; |
| | | if (res.code === 200) { |
| | | proxy.$modal.msgSuccess("ç»è®°æå"); |
| | | closeAndRefresh(); |
| | | } |
| | | }).catch(() => { |
| | | modalLoading.value = false; |
| | | proxy.$modal.msgError("ç»è®°å¤±è´¥"); |
| | | }); |
| | | } |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | defineExpose({ |
| | | open, |
| | | closeAndRefresh, |
| | | open, |
| | | closeAndRefresh, |
| | | }); |
| | | </script> |
| | | |
| | |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="项ç®åç§°"> |
| | | <el-input |
| | | v-model="filters.projectName" |
| | | placeholder="请è¾å
¥é¡¹ç®åç§°" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="getTableData"> æç´¢ </el-button> |
| | | <el-button @click="resetFilters"> éç½® </el-button> |
| | |
| | | <div> |
| | | <el-button @click="handleExport" style="margin-right: 10px">导åº</el-button> |
| | | <el-button type="primary" @click="handleAdd('add')"> |
| | | æ°å¢ç»è®° |
| | | æ¥ç¥¨ç»è®° |
| | | </el-button> |
| | | <!-- <el-button type="danger" plain @click="handleDelete">å é¤</el-button>--> |
| | | </div> |
| | |
| | | width:300 |
| | | }, |
| | | { |
| | | label: "项ç®åç§°", |
| | | prop: "projectName", |
| | | width:400 |
| | | }, |
| | | { |
| | | label: "å½å
¥äºº", |
| | | prop: "recorderName", |
| | | }, |
| | |
| | | }; |
| | | |
| | | const handleAdd = (type) => { |
| | | if (selectedRows.value.length !== 1) { |
| | | proxy.$modal.msgWarning("请å
éä¸ä¸æ¡æ°æ®"); |
| | | return; |
| | | } |
| | | modalRef.value.open(type, selectedRows.value[0].id); |
| | | if (selectedRows.value.length < 1) { |
| | | proxy.$modal.msgWarning("请è³å°éä¸ä¸æ¡æ°æ®"); |
| | | return; |
| | | } |
| | | modalRef.value.open(type, selectedRows.value); |
| | | }; |
| | | |
| | | const handleEdit = (type, id) => { |
| | |
| | | </el-col> |
| | | <el-col :span="4"> |
| | | <el-form-item style="float: right; margin-right: unset"> |
| | | <el-button @click="handleExport" style="margin-right: 10px">导åº</el-button> |
| | | <el-button type="primary" @click="openForm('add')"> |
| | | æ°å¢ä»æ¬¾ |
| | | </el-button> |
| | | <el-button @click="handleExport" style="margin-right: 10px">导åº</el-button> |
| | | <!-- <el-button type="danger" plain @click="handleDelete">--> |
| | | <!-- å é¤--> |
| | | <!-- </el-button>--> |
| | |
| | | </template> |
| | | </PIMTable> |
| | | </div> |
| | | <el-dialog |
| | | <FormDialog |
| | | v-model="dialogFormVisible" |
| | | :title="operationType === 'add' ? 'æ°å¢ä»æ¬¾ç»è®°' : 'ç¼è¾ä»æ¬¾ç»è®°'" |
| | | width="60%" |
| | | title="æ°å¢ä»æ¬¾é¡µé¢" |
| | | :width="'90%'" |
| | | @close="closeDia" |
| | | @confirm="submitForm" |
| | | @cancel="closeDia" |
| | | > |
| | | <el-form |
| | | :model="form" |
| | | label-width="140px" |
| | | label-position="top" |
| | | :rules="rules" |
| | | ref="formRef" |
| | | <el-table |
| | | v-if="forms.length" |
| | | :data="forms" |
| | | border |
| | | style="width: 100%" |
| | | size="small" |
| | | > |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="éè´ååå·ï¼" prop="purchaseContractNumber"> |
| | | <el-input |
| | | v-model="form.purchaseContractNumber" |
| | | placeholder="èªå¨å¡«å
" |
| | | clearable |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="éå®ååå·ï¼" prop="salesContractNo"> |
| | | <el-input |
| | | v-model="form.salesContractNo" |
| | | placeholder="èªå¨å¡«å
" |
| | | clearable |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ä¾åºååç§°ï¼" prop="supplierName"> |
| | | <el-input |
| | | v-model="form.supplierName" |
| | | placeholder="èªå¨å¡«å
" |
| | | clearable |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å票å·ï¼" prop="invoiceNumber"> |
| | | <el-input |
| | | v-model="form.invoiceNumber" |
| | | placeholder="èªå¨å¡«å
" |
| | | clearable |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å票éé¢(å
)ï¼" prop="invoiceAmount"> |
| | | <el-input |
| | | v-model="form.invoiceAmount" |
| | | placeholder="èªå¨å¡«å
" |
| | | clearable |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ¬æ¬¡ä»æ¬¾éé¢ï¼" prop="currentPaymentAmount"> |
| | | <el-input-number :step="0.01" :min="0" style="width: 100%" |
| | | :precision="2" |
| | | v-model="form.currentPaymentAmount" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="仿¬¾æ¹å¼ï¼" prop="paymentMethod"> |
| | | <el-select |
| | | v-model="form.paymentMethod" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | > |
| | | <el-option label="çµæ±" value="çµæ±" /> |
| | | <el-option label="æ¿å
" value="æ¿å
" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="仿¬¾æ¥æï¼" prop="paymentDate"> |
| | | <el-date-picker |
| | | style="width: 100%" |
| | | v-model="form.paymentDate" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="date" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç»è®°äººï¼" prop="registrant"> |
| | | <el-input |
| | | v-model="form.registrant" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç»è®°æ¥æï¼" prop="registrationtDate"> |
| | | <el-input |
| | | v-model="form.registrationtDate" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="submitForm">确认</el-button> |
| | | <el-button @click="closeDia">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | <el-table-column type="index" label="åºå·" width="50" align="center"/> |
| | | <el-table-column label="éè´ååå·" prop="purchaseContractNumber" show-overflow-tooltip /> |
| | | <el-table-column label="éå®ååå·" prop="salesContractNo" show-overflow-tooltip /> |
| | | <el-table-column label="ä¾åºååç§°" prop="supplierName" show-overflow-tooltip /> |
| | | <el-table-column |
| | | label="产å大类" |
| | | prop="productCategory" |
| | | show-overflow-tooltip |
| | | width="100" |
| | | /> |
| | | <el-table-column |
| | | label="è§æ ¼åå·" |
| | | prop="specificationModel" |
| | | show-overflow-tooltip |
| | | width="150" |
| | | /> |
| | | <el-table-column |
| | | label="å¾
仿¬¾éé¢(å
)" |
| | | prop="pendingTicketsTotal" |
| | | show-overflow-tooltip |
| | | width="170" |
| | | > |
| | | <template #default="{ row, column }"> |
| | | <el-text type="danger"> |
| | | {{ formattedNumber(row, column, row.pendingTicketsTotal) }} |
| | | </el-text> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="æ¬æ¬¡ä»æ¬¾éé¢(å
)" width="180"> |
| | | <template #default="{ row }"> |
| | | <el-input-number |
| | | v-model="row.currentPaymentAmount" |
| | | :step="0.01" |
| | | :min="0" |
| | | :max="Number(row.pendingTicketsTotal || 0)" |
| | | :precision="2" |
| | | style="width: 100%" |
| | | placeholder="请è¾å
¥" |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="仿¬¾æ¹å¼" width="160"> |
| | | <template #default="{ row }"> |
| | | <el-select v-model="row.paymentMethod" placeholder="è¯·éæ©" clearable> |
| | | <el-option label="çµæ±" value="çµæ±" /> |
| | | <el-option label="æ¿å
" value="æ¿å
" /> |
| | | </el-select> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="仿¬¾æ¥æ" width="170"> |
| | | <template #default="{ row }"> |
| | | <el-date-picker |
| | | v-model="row.paymentDate" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="date" |
| | | placeholder="è¯·éæ©" |
| | | style="width: 100%" |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="ç»è®°äºº" width="140"> |
| | | <template #default="{ row }"> |
| | | <el-input v-model="row.registrant" disabled /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="ç»è®°æ¥æ" width="170"> |
| | | <template #default="{ row }"> |
| | | <el-input v-model="row.registrationtDate" /> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <div v-else class="empty-tip">è¯·éæ©éè¦ä»æ¬¾çè®°å½</div> |
| | | </FormDialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import FormDialog from '@/components/Dialog/FormDialog.vue'; |
| | | import { ref, reactive, toRefs, getCurrentInstance, nextTick, onMounted } from "vue"; |
| | | import { Search } from "@element-plus/icons-vue"; |
| | | import { ElMessageBox } from "element-plus"; |
| | |
| | | { |
| | | label: "éè´ååå·", |
| | | prop: "purchaseContractNumber", |
| | | width:160 |
| | | }, |
| | | { |
| | | label: "éå®ååå·", |
| | | prop: "salesContractNo", |
| | | width:160 |
| | | }, |
| | | { |
| | | label: "ä¾åºååç§°", |
| | |
| | | { |
| | | label: "仿¬¾ç¶æ", |
| | | prop: "statusName", |
| | | width:110, |
| | | dataType: "tag", |
| | | formatType: (params) => { |
| | | if (params == 'æªå®æä»æ¬¾') { |
| | |
| | | } |
| | | }, |
| | | }, |
| | | { |
| | | label: "å票å·", |
| | | prop: "invoiceNumber", |
| | | width:200 |
| | | }, |
| | | { |
| | | label: "å票éé¢(å
)", |
| | | prop: "invoiceAmount", |
| | | formatData: (params) => { |
| | | return params ? parseFloat(params).toFixed(2) : 0; |
| | | }, |
| | | }, |
| | | { |
| | | label: "产å大类", |
| | | prop: "productCategory", |
| | | showOverflowTooltip: true, |
| | | width: 100 |
| | | }, |
| | | { |
| | | label: "è§æ ¼åå·", |
| | | prop: "specificationModel", |
| | | showOverflowTooltip: true, |
| | | width: 150 |
| | | }, |
| | | { |
| | | label: "已仿¬¾éé¢(å
)", |
| | | prop: "paymentAmountTotal", |
| | | prop: "ticketsTotal", |
| | | width: 120, |
| | | formatData: (params) => { |
| | | return params ? parseFloat(params).toFixed(2) : 0; |
| | | }, |
| | | }, |
| | | { |
| | | label: "å¾
仿¬¾éé¢(å
)", |
| | | prop: "unPaymentAmountTotal", |
| | | prop: "pendingTicketsTotal", |
| | | width: 120, |
| | | formatData: (params) => { |
| | | return params ? parseFloat(params).toFixed(2) : 0; |
| | | }, |
| | | }, |
| | | { |
| | | label: "å½å
¥äºº", |
| | | prop: "issUer", |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | |
| | | const selectedRows = ref([]); |
| | | const tableLoading = ref(false); |
| | | const childrenLoading = ref(false); |
| | | const forms = ref([]); |
| | | const userStore = useUserStore(); |
| | | const page = reactive({ |
| | | current: 1, |
| | |
| | | purchaseLedgerId: "", |
| | | salesContractNo: "", |
| | | supplierName: "", |
| | | invoiceNumber: "", |
| | | invoiceAmount: "", |
| | | taxRate: "", |
| | | currentPaymentAmount: "", |
| | | paymentMethod: "", |
| | |
| | | { required: true, message: "请è¾å
¥", trigger: "blur" }, |
| | | ], |
| | | paymentMethod: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | invoiceNumber: [ |
| | | { required: true, message: "è¯·éæ©éè´ååå·", trigger: "change" }, |
| | | ], |
| | | }, |
| | | }); |
| | | const { form, rules } = toRefs(data); |
| | |
| | | if (!normalized) return 'info'; |
| | | return normalized === 'æªå®æä»æ¬¾' ? 'danger' : 'success'; |
| | | }; |
| | | |
| | | const formattedNumber = (row, column, cellValue) => { |
| | | const val = Number(cellValue ?? 0); |
| | | return Number.isFinite(val) ? val.toFixed(2) : "0.00"; |
| | | }; |
| | | // å表åè®¡æ¹æ³ |
| | | const summarizeMainTable1 = (param) => { |
| | | return proxy.summarizeTable( |
| | | param, |
| | | ["invoiceAmount", "paymentAmountTotal", "unPaymentAmountTotal"], |
| | | ["ticketsTotal", "pendingTicketsTotal"], |
| | | { |
| | | ticketsNum: { noDecimal: true }, // ä¸ä¿çå°æ° |
| | | futureTickets: { noDecimal: true }, // ä¸ä¿çå°æ° |
| | |
| | | tableLoading.value = true; |
| | | invoiceListPage({ ...searchForm, ...page }).then((res) => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.records; |
| | | page.total = res.total; |
| | | tableData.value = res.data.records; |
| | | page.total = res.data.total; |
| | | if (expandedRowKeys.value.length > 0) { |
| | | const arr = [] |
| | | const index = tableData.value.findIndex(item => item.id === expandedRowKeys.value[0]); |
| | |
| | | }; |
| | | // æå¼å¼¹æ¡ |
| | | const openForm = (type, row) => { |
| | | if (selectedRows.value.length !== 1) { |
| | | proxy.$message.error("è¯·éæ©ä¸æ¡åç¥¨æ°æ®"); |
| | | if (selectedRows.value.length === 0) { |
| | | proxy.$modal.msgError("è¯·éæ©è³å°ä¸æ¡æ°æ®"); |
| | | return; |
| | | } |
| | | if (selectedRows.value[0].unPaymentAmountTotal == 0) { |
| | | proxy.$message.warning("æ éå仿¬¾"); |
| | | return; |
| | | } |
| | | operationType.value = type; |
| | | form.value = {}; |
| | | form.value = { ...selectedRows.value[0] }; |
| | | form.value.ticketRegistrationId = selectedRows.value[0].id; |
| | | form.value.id = null; |
| | | // æ¥è¯¢éè´ååå· |
| | | form.value.registrationtDate = getCurrentDate(); |
| | | form.value.paymentDate = getCurrentDate(); |
| | | form.value.registrant = userStore.name; |
| | | const validRows = selectedRows.value.filter((item) => Number(item.pendingTicketsTotal || 0) !== 0); |
| | | if (validRows.length === 0) { |
| | | proxy.$modal.msgWarning("æéè®°å½åæ é仿¬¾"); |
| | | return; |
| | | } |
| | | forms.value = validRows.map((row) => ({ |
| | | purchaseContractNumber: row.purchaseContractNumber || "", |
| | | salesContractNo: row.salesContractNo || "", |
| | | supplierName: row.supplierName || "", |
| | | supplierId: row.supplierId, |
| | | productCategory: row.productCategory || "", |
| | | specificationModel: row.specificationModel || "", |
| | | pendingTicketsTotal: Number(row.pendingTicketsTotal || 0), |
| | | currentPaymentAmount: "", |
| | | paymentMethod: "", |
| | | paymentDate: "", |
| | | registrant: userStore.nickName, |
| | | registrationtDate: getCurrentDate(), |
| | | ticketRegistrationId: row.id, |
| | | purchaseLedgerId: row.salesLedgerId, |
| | | salesLedgerProductId: row.id, |
| | | })); |
| | | dialogFormVisible.value = true; |
| | | }; |
| | | // æäº¤è¡¨å |
| | | const submitForm = () => { |
| | | proxy.$refs["formRef"].validate((valid) => { |
| | | if (valid) { |
| | | if (operationType.value === "edit") { |
| | | submitEdit(); |
| | | } else { |
| | | submitAdd(); |
| | | } |
| | | if (forms.value.length === 0) { |
| | | proxy.$modal.msgError("è¯·éæ©ä»æ¬¾è®°å½"); |
| | | return; |
| | | } |
| | | for (let i = 0; i < forms.value.length; i++) { |
| | | const item = forms.value[i]; |
| | | const pendingAmount = Number(item.pendingTicketsTotal || 0); |
| | | const currentAmount = Number(item.currentPaymentAmount); |
| | | if (!item.currentPaymentAmount && item.currentPaymentAmount !== 0) { |
| | | proxy.$modal.msgError(`第 ${i + 1} æ¡ï¼è¯·å¡«å仿¬¾éé¢`); |
| | | return; |
| | | } |
| | | }); |
| | | }; |
| | | // æäº¤æ°å¢ |
| | | const submitAdd = () => { |
| | | paymentRegistrationAdd(form.value).then((res) => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeDia(); |
| | | getList(); |
| | | }); |
| | | }; |
| | | // æäº¤ä¿®æ¹ |
| | | const submitEdit = () => { |
| | | paymentRegistrationEdit(form.value).then((res) => { |
| | | if (currentAmount > pendingAmount) { |
| | | proxy.$modal.msgError( |
| | | `第 ${i + 1} æ¡ï¼ä»æ¬¾éé¢ä¸è½è¶
è¿å¾
仿¬¾éé¢ï¼å¾
仿¬¾ï¼${pendingAmount.toFixed( |
| | | 2 |
| | | )}ï¼` |
| | | ); |
| | | return; |
| | | } |
| | | if (!item.paymentMethod) { |
| | | proxy.$modal.msgError(`第 ${i + 1} æ¡ï¼è¯·éæ©ä»æ¬¾æ¹å¼`); |
| | | return; |
| | | } |
| | | if (!item.paymentDate) { |
| | | proxy.$modal.msgError(`第 ${i + 1} æ¡ï¼è¯·éæ©ä»æ¬¾æ¥æ`); |
| | | return; |
| | | } |
| | | } |
| | | paymentRegistrationAdd(forms.value).then(() => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeDia(); |
| | | getList(); |
| | |
| | | }; |
| | | // å
³éå¼¹æ¡ |
| | | const closeDia = () => { |
| | | proxy.resetForm("formRef"); |
| | | forms.value = []; |
| | | dialogFormVisible.value = false; |
| | | }; |
| | | // å é¤ |
| | |
| | | }) |
| | | .then(() => { |
| | | tableLoading.value = true; |
| | | delPaymentRegistration(row.id) |
| | | delPaymentRegistration([row.id]) |
| | | .then((res) => { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | getList(); |
| | |
| | | ::v-deep(.el-checkbox__label) { |
| | | font-weight: bold; |
| | | } |
| | | .empty-tip { |
| | | text-align: center; |
| | | padding: 20px 0; |
| | | color: #909399; |
| | | } |
| | | </style> |
| | |
| | | æç´¢ |
| | | </el-button> |
| | | <el-button @click="handleExport">导åº</el-button> |
| | | <el-button |
| | | type="danger" |
| | | :disabled="selectedRows.length === 0" |
| | | @click="handleBatchDelete" |
| | | > |
| | | æ¹éå é¤ ({{ selectedRows.length }}) |
| | | </el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | <div class="table_list"> |
| | |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | :total="page.total" |
| | | ></PIMTable> |
| | | > |
| | | <template #operation="{ row }"> |
| | | <el-button |
| | | type="primary" |
| | | link |
| | | size="small" |
| | | @click="handleDelete(row)" |
| | | > |
| | | å é¤ |
| | | </el-button> |
| | | </template> |
| | | </PIMTable> |
| | | </div> |
| | | </div> |
| | | </template> |
| | |
| | | <script setup> |
| | | import { ref, reactive, getCurrentInstance, onMounted } from "vue"; |
| | | import { Search } from "@element-plus/icons-vue"; |
| | | import { paymentHistoryListPage } from "@/api/procurementManagement/paymentEntry.js"; |
| | | import { ElMessageBox } from "element-plus"; |
| | | import { paymentHistoryListPage} from "@/api/procurementManagement/paymentEntry.js"; |
| | | import {delPaymentRegistration } from "@/api/procurementManagement/procurementInvoiceLedger.js"; |
| | | import useFormData from "@/hooks/useFormData"; |
| | | import dayjs from "dayjs"; |
| | | |
| | |
| | | { |
| | | label: "ç»è®°æ¥æ", |
| | | prop: "registrationtDate", |
| | | }, |
| | | { |
| | | label: "æä½", |
| | | dataType: "slot", |
| | | slot: "operation", |
| | | width: 100, |
| | | align: "center", |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | |
| | | getList(); |
| | | }; |
| | | |
| | | // å é¤ |
| | | const handleDelete = (row) => { |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼", "å é¤æç¤º", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | tableLoading.value = true; |
| | | delPaymentRegistration([row.id]) |
| | | .then((res) => { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | getList(); |
| | | }) |
| | | .finally(() => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | |
| | | // æ¹éå é¤ |
| | | const handleBatchDelete = () => { |
| | | if (selectedRows.value.length === 0) { |
| | | proxy.$modal.msgWarning("è¯·éæ©è¦å é¤çæ°æ®"); |
| | | return; |
| | | } |
| | | ElMessageBox.confirm( |
| | | `ç¡®å®è¦å é¤éä¸ç ${selectedRows.value.length} æ¡æ°æ®åï¼`, |
| | | "å é¤æç¤º", |
| | | { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | } |
| | | ) |
| | | .then(() => { |
| | | tableLoading.value = true; |
| | | const ids = selectedRows.value.map((item) => item.id); |
| | | delPaymentRegistration(ids) |
| | | .then((res) => { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | selectedRows.value = []; |
| | | getList(); |
| | | }) |
| | | .finally(() => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | |
| | | // å¯¼åº |
| | | const handleExport = () => { |
| | | const { paymentDate, ...rest } = searchForm; |
| | |
| | | /> |
| | | <el-table-column label="ä¾åºååç§°" prop="supplierName" /> |
| | | <el-table-column |
| | | label="å票éé¢(å
)" |
| | | label="ååéé¢(å
)" |
| | | prop="invoiceAmount" |
| | | show-overflow-tooltip |
| | | :formatter="formattedNumber" |
| | |
| | | :column="tableColumnSon" |
| | | :tableData="originalTableDataSon" |
| | | :isSelection="false" |
| | | :isShowPagination="false" |
| | | :tableLoading="tableLoadingSon" |
| | | :isShowSummary="isShowSummarySon" |
| | | :summaryMethod="summarizeMainTable1" |
| | |
| | | </el-text> |
| | | </template> |
| | | </PIMTable> |
| | | <pagination |
| | | v-show="sonTotal > 0" |
| | | :total="sonTotal" |
| | | @pagination="sonPaginationSearch" |
| | | :layout="page.layout" |
| | | :page="sonPage.current" |
| | | :limit="sonPage.size" |
| | | /> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | |
| | | } from "@/api/procurementManagement/paymentLedger.js"; |
| | | import Pagination from "../../../components/PIMTable/Pagination.vue"; |
| | | |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "ä¾åºååç§°", |
| | | prop: "supplierName", |
| | | width:240 |
| | | }, |
| | | { |
| | | label: "å票éé¢(å
)", |
| | | prop: "invoiceAmount", |
| | | }, |
| | | { |
| | | label: "仿¬¾éé¢(å
)", |
| | | prop: "paymentAmount", |
| | | }, |
| | | { |
| | | label: "åºä»éé¢(å
)", |
| | | prop: "payableAmount", |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | | const tableLoading = ref(false); |
| | | const data = reactive({ |
| | |
| | | const tableColumnSon = ref([ |
| | | { |
| | | label: "åçæ¥æ", |
| | | prop: "happenTime", |
| | | prop: "paymentDate", |
| | | width: 110, |
| | | }, |
| | | { |
| | | label: "å票éé¢(å
)", |
| | | label: "éè´ååå·", |
| | | prop: "purchaseContractNumber", |
| | | width: 150, |
| | | }, |
| | | { |
| | | label: "ååéé¢(å
)", |
| | | prop: "invoiceAmount", |
| | | width: 200, |
| | | formatData: (params) => { |
| | |
| | | }, |
| | | { |
| | | label: "仿¬¾éé¢(å
)", |
| | | prop: "currentPaymentAmount", |
| | | prop: "paymentAmount", |
| | | width: 200, |
| | | formatData: (params) => { |
| | | return params ? parseFloat(params).toFixed(2) : 0; |
| | |
| | | const summarizeMainTable1 = (param) => { |
| | | let summarizeTable = proxy.summarizeTable( |
| | | param, |
| | | ["invoiceAmount", "currentPaymentAmount"], |
| | | ["invoiceAmount", "paymentAmount"], |
| | | { |
| | | ticketsNum: { noDecimal: true }, // ä¸ä¿çå°æ° |
| | | futureTickets: { noDecimal: true }, // ä¸ä¿çå°æ° |
| | |
| | | paymentLedgerList({ |
| | | ...searchForm.value, |
| | | ...page, |
| | | detailPageNum: detailPageNum.value, // æ°å¢ |
| | | detailPageSize: detailPageSize.value, // æ°å¢ |
| | | }).then((res) => { |
| | | let result = res.data; |
| | | tableLoading.value = false; |
| | |
| | | </el-table> |
| | | </el-card> |
| | | |
| | | <el-dialog v-model="dialogVisible" :title="dialogType === 'add' ? 'æ°å¢ä»·æ ¼' : 'ç¼è¾ä»·æ ¼'" width="600px"> |
| | | <FormDialog v-model="dialogVisible" :title="dialogType === 'add' ? 'æ°å¢ä»·æ ¼' : 'ç¼è¾ä»·æ ¼'" :width="'600px'" :operation-type="dialogType" @close="dialogVisible = false" @confirm="handleSubmit" @cancel="dialogVisible = false"> |
| | | <el-form :model="formData" label-width="120px"> |
| | | <el-form-item label="åååç§°"> |
| | | <el-select v-model="formData.productName" placeholder="è¯·éæ©åå" style="width: 100%"> |
| | |
| | | <el-input v-model="formData.remark" type="textarea" :rows="3" placeholder="请è¾å
¥å¤æ³¨ä¿¡æ¯" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <el-button @click="dialogVisible = false">åæ¶</el-button> |
| | | <el-button type="primary" @click="handleSubmit">ç¡®å®</el-button> |
| | | </template> |
| | | </el-dialog> |
| | | </FormDialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import FormDialog from '@/components/Dialog/FormDialog.vue'; |
| | | import { ref, reactive, computed } from 'vue' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <el-dialog v-model="dialogVisible" title="éä»¶" width="40%" :before-close="handleClose"> |
| | | <el-table :data="tableData" border height="40vh"> |
| | | <el-table-column label="éä»¶åç§°" prop="name" min-width="400" show-overflow-tooltip /> |
| | | <el-table-column fixed="right" label="æä½" width="150" align="center"> |
| | | <template #default="scope"> |
| | | <el-button link type="primary" size="small" @click="downLoadFile(scope.row)">ä¸è½½</el-button> |
| | | <el-button link type="primary" size="small" @click="lookFile(scope.row)">é¢è§</el-button> |
| | | <el-button link type="danger" size="small" @click="handleDelete(scope.row)">å é¤</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </el-dialog> |
| | | <filePreview ref="filePreviewRef" /> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref } from 'vue' |
| | | import { ElMessageBox, ElMessage } from 'element-plus' |
| | | import filePreview from '@/components/filePreview/index.vue' |
| | | import { delCommonFile } from '@/api/publicApi/commonFile.js' |
| | | |
| | | const dialogVisible = ref(false) |
| | | const tableData = ref([]) |
| | | const { proxy } = getCurrentInstance(); |
| | | const filePreviewRef = ref() |
| | | const handleClose = () => { |
| | | dialogVisible.value = false |
| | | } |
| | | const open = (list) => { |
| | | dialogVisible.value = true |
| | | tableData.value = list |
| | | } |
| | | const downLoadFile = (row) => { |
| | | proxy.$download.name(row.url); |
| | | |
| | | } |
| | | const lookFile = (row) => { |
| | | filePreviewRef.value.open(row.url) |
| | | } |
| | | // å é¤éä»¶ |
| | | const handleDelete = (row) => { |
| | | ElMessageBox.confirm(`确认å é¤éä»¶"${row.name}"åï¼`, 'å é¤ç¡®è®¤', { |
| | | confirmButtonText: '确认', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning', |
| | | }).then(() => { |
| | | delCommonFile([row.id]).then(() => { |
| | | ElMessage.success('å 餿å') |
| | | // ä»å表ä¸ç§»é¤å·²å é¤çéä»¶ |
| | | const index = tableData.value.findIndex(item => item.id === row.id) |
| | | if (index !== -1) { |
| | | tableData.value.splice(index, 1) |
| | | } |
| | | }).catch(() => { |
| | | ElMessage.error('å é¤å¤±è´¥') |
| | | }) |
| | | }).catch(() => { |
| | | proxy.$modal.msg('已忶å é¤') |
| | | }) |
| | | } |
| | | defineExpose({ |
| | | open |
| | | }) |
| | | </script> |
| | | |
| | | <style></style> |
| | |
| | | <div class="app-container"> |
| | | <div class="search_form"> |
| | | <div> |
| | | <el-form :model="searchForm" :inline="true"> |
| | | <el-form :model="searchForm" |
| | | :inline="true"> |
| | | <el-form-item label="ä¾åºååç§°ï¼"> |
| | | <el-input v-model="searchForm.supplierName" placeholder="请è¾å
¥" clearable prefix-icon="Search" |
| | | <el-input v-model="searchForm.supplierName" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | prefix-icon="Search" |
| | | @change="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="éè´ååå·ï¼"> |
| | | <el-input |
| | | v-model="searchForm.purchaseContractNumber" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥" |
| | | @change="handleQuery" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | /> |
| | | <el-input v-model="searchForm.purchaseContractNumber" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥" |
| | | @change="handleQuery" |
| | | clearable |
| | | :prefix-icon="Search" /> |
| | | </el-form-item> |
| | | <el-form-item label="éå®ååå·ï¼"> |
| | | <el-input v-model="searchForm.salesContractNo" placeholder="请è¾å
¥" clearable prefix-icon="Search" |
| | | <el-input v-model="searchForm.salesContractNo" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | prefix-icon="Search" |
| | | @change="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="项ç®åç§°ï¼"> |
| | | <el-input v-model="searchForm.projectName" placeholder="请è¾å
¥" clearable prefix-icon="Search" |
| | | <el-input v-model="searchForm.projectName" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | prefix-icon="Search" |
| | | @change="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="å½å
¥æ¥æï¼"> |
| | | <el-date-picker v-model="searchForm.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="daterange" |
| | | placeholder="è¯·éæ©" clearable @change="changeDaterange" /> |
| | | <el-date-picker v-model="searchForm.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="handleQuery"> æç´¢ </el-button> |
| | | <el-button type="primary" |
| | | @click="handleQuery"> æç´¢ </el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | |
| | | </div> |
| | | <div class="table_list"> |
| | | <div style="display: flex;justify-content: flex-end;margin-bottom: 20px;"> |
| | | <el-button type="primary" @click="openForm('add')">æ°å¢å°è´¦</el-button> |
| | | <el-button type="success" @click="openScanAddDialog">æ«ç æ°å¢</el-button> |
| | | <el-button type="primary" |
| | | @click="openForm('add')">æ°å¢å°è´¦</el-button> |
| | | <el-button type="success" |
| | | @click="openScanAddDialog">æ«ç æ°å¢</el-button> |
| | | <el-button @click="handleOut">导åº</el-button> |
| | | <el-button type="danger" plain @click="handleDelete">å é¤</el-button> |
| | | <el-button type="danger" |
| | | plain |
| | | @click="handleDelete">å é¤</el-button> |
| | | </div> |
| | | <el-table |
| | | :data="tableData" |
| | | border |
| | | v-loading="tableLoading" |
| | | @selection-change="handleSelectionChange" |
| | | :expand-row-keys="expandedRowKeys" |
| | | :row-key="(row) => row.id" |
| | | show-summary |
| | | :summary-method="summarizeMainTable" |
| | | @expand-change="expandChange" |
| | | height="calc(100vh - 18.5em)" |
| | | :row-class-name="tableRowClassName" |
| | | > |
| | | <el-table-column align="center" type="selection" width="55" /> |
| | | <el-table :data="tableData" |
| | | border |
| | | v-loading="tableLoading" |
| | | @selection-change="handleSelectionChange" |
| | | :expand-row-keys="expandedRowKeys" |
| | | :row-key="(row) => row.id" |
| | | show-summary |
| | | :summary-method="summarizeMainTable" |
| | | @expand-change="expandChange" |
| | | height="calc(100vh - 19em)" |
| | | :row-class-name="tableRowClassName"> |
| | | <el-table-column align="center" |
| | | type="selection" |
| | | width="55" /> |
| | | <el-table-column type="expand"> |
| | | <template #default="props"> |
| | | <el-table |
| | | :data="props.row.children" |
| | | border |
| | | show-summary |
| | | :summary-method="summarizeChildrenTable" |
| | | > |
| | | <el-table-column |
| | | align="center" |
| | | label="åºå·" |
| | | type="index" |
| | | width="60" |
| | | /> |
| | | <el-table-column label="产å大类" prop="productCategory" /> |
| | | <el-table-column label="è§æ ¼åå·" prop="specificationModel" /> |
| | | <el-table-column label="åä½" prop="unit" /> |
| | | <el-table-column label="æ°é" prop="quantity" /> |
| | | <el-table-column label="ç¨ç(%)" prop="taxRate" /> |
| | | <el-table-column |
| | | label="å«ç¨åä»·(å
)" |
| | | prop="taxInclusiveUnitPrice" |
| | | :formatter="formattedNumber" |
| | | /> |
| | | <el-table-column |
| | | label="å«ç¨æ»ä»·(å
)" |
| | | prop="taxInclusiveTotalPrice" |
| | | :formatter="formattedNumber" |
| | | /> |
| | | <el-table-column |
| | | label="ä¸å«ç¨æ»ä»·(å
)" |
| | | prop="taxExclusiveTotalPrice" |
| | | :formatter="formattedNumber" |
| | | /> |
| | | <el-table :data="props.row.children" |
| | | border |
| | | show-summary |
| | | :summary-method="summarizeChildrenTable"> |
| | | <el-table-column align="center" |
| | | label="åºå·" |
| | | type="index" |
| | | width="60" /> |
| | | <el-table-column label="产å大类" |
| | | prop="productCategory" /> |
| | | <el-table-column label="è§æ ¼åå·" |
| | | prop="specificationModel" /> |
| | | <el-table-column label="åä½" |
| | | prop="unit" /> |
| | | <el-table-column label="æ°é" |
| | | prop="quantity" /> |
| | | <el-table-column label="ç¨ç(%)" |
| | | prop="taxRate" /> |
| | | <el-table-column label="å«ç¨åä»·(å
)" |
| | | prop="taxInclusiveUnitPrice" |
| | | :formatter="formattedNumber" /> |
| | | <el-table-column label="å«ç¨æ»ä»·(å
)" |
| | | prop="taxInclusiveTotalPrice" |
| | | :formatter="formattedNumber" /> |
| | | <el-table-column label="ä¸å«ç¨æ»ä»·(å
)" |
| | | prop="taxExclusiveTotalPrice" |
| | | :formatter="formattedNumber" /> |
| | | </el-table> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column align="center" label="åºå·" type="index" width="60" /> |
| | | <el-table-column |
| | | label="éè´ååå·" |
| | | prop="purchaseContractNumber" |
| | | width="200" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | | label="éå®ååå·" |
| | | prop="salesContractNo" |
| | | width="200" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | | label="ä¾åºååç§°" |
| | | width="240" |
| | | prop="supplierName" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column label="订åç¶æ" width="100" align="center"> |
| | | <el-table-column align="center" |
| | | label="åºå·" |
| | | type="index" |
| | | width="60" /> |
| | | <el-table-column label="éè´ååå·" |
| | | prop="purchaseContractNumber" |
| | | width="200" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="éå®ååå·" |
| | | prop="salesContractNo" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="ä¾åºååç§°" |
| | | prop="supplierName" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="订åç¶æ" |
| | | width="100" |
| | | align="center"> |
| | | <template #default="scope"> |
| | | <el-tag v-if="scope.row.isInvalid" type="danger" size="small">失æ</el-tag> |
| | | <el-tag v-else type="success" size="small">æ£å¸¸</el-tag> |
| | | <el-tag v-if="scope.row.isInvalid" |
| | | type="danger" |
| | | size="small">失æ</el-tag> |
| | | <el-tag v-else |
| | | type="success" |
| | | size="small">æ£å¸¸</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="项ç®åç§°" |
| | | prop="projectName" |
| | | width="420" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | | label="审æ¹ç¶æ" |
| | | prop="approvalStatus" |
| | | width="200" |
| | | show-overflow-tooltip |
| | | > |
| | | <el-table-column label="项ç®åç§°" |
| | | prop="projectName" |
| | | width="420" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="审æ¹ç¶æ" |
| | | prop="approvalStatus" |
| | | width="200" |
| | | show-overflow-tooltip> |
| | | <template #default="scope"> |
| | | <el-tag |
| | | size="small" |
| | | > |
| | | <el-tag size="small"> |
| | | {{ approvalStatusText[scope.row.approvalStatus] || 'æªç¥ç¶æ' }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="仿¬¾æ¹å¼" |
| | | width="100" |
| | | prop="paymentMethod" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | | label="ååéé¢(å
)" |
| | | prop="contractAmount" |
| | | width="200" |
| | | show-overflow-tooltip |
| | | :formatter="formattedNumber" |
| | | /> |
| | | <el-table-column |
| | | label="å½å
¥äºº" |
| | | prop="recorderName" |
| | | width="100" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | | label="å½å
¥æ¥æ" |
| | | prop="entryDate" |
| | | width="100" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | | fixed="right" |
| | | label="æä½" |
| | | min-width="150" |
| | | align="center" |
| | | > |
| | | <el-table-column label="ç¾è®¢æ¥æ" |
| | | prop="executionDate" |
| | | width="100" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="仿¬¾æ¹å¼" |
| | | width="100" |
| | | prop="paymentMethod" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="ååéé¢(å
)" |
| | | prop="contractAmount" |
| | | width="200" |
| | | show-overflow-tooltip |
| | | :formatter="formattedNumber" /> |
| | | <el-table-column label="å½å
¥äºº" |
| | | prop="recorderName" |
| | | width="120" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="å½å
¥æ¥æ" |
| | | prop="entryDate" |
| | | width="100" |
| | | show-overflow-tooltip /> |
| | | <el-table-column fixed="right" |
| | | label="æä½" |
| | | width="180" |
| | | align="center"> |
| | | <template #default="scope"> |
| | | <el-button |
| | | link |
| | | type="primary" |
| | | size="small" |
| | | @click="openForm('edit', scope.row)" |
| | | >ç¼è¾</el-button |
| | | > |
| | | <el-button |
| | | link |
| | | type="success" |
| | | size="small" |
| | | @click="showQRCode(scope.row)" |
| | | >çæäºç»´ç </el-button |
| | | > |
| | | |
| | | <el-button link |
| | | type="primary" |
| | | size="small" |
| | | @click="openForm('edit', scope.row)">ç¼è¾</el-button> |
| | | <el-button link |
| | | type="success" |
| | | size="small" |
| | | @click="showQRCode(scope.row)">çæäºç»´ç </el-button> |
| | | <el-button link |
| | | type="primary" |
| | | size="small" |
| | | @click="downLoadFile(scope.row)">éä»¶</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <pagination |
| | | v-show="total > 0" |
| | | :total="total" |
| | | layout="total, sizes, prev, pager, next, jumper" |
| | | :page="page.current" |
| | | :limit="page.size" |
| | | @pagination="paginationChange" |
| | | /> |
| | | <pagination v-show="total > 0" |
| | | :total="total" |
| | | layout="total, sizes, prev, pager, next, jumper" |
| | | :page="page.current" |
| | | :limit="page.size" |
| | | @pagination="paginationChange" /> |
| | | </div> |
| | | <el-dialog |
| | | v-model="dialogFormVisible" |
| | | :title="operationType === 'add' ? 'æ°å¢éè´å°è´¦é¡µé¢' : 'ç¼è¾éè´å°è´¦é¡µé¢'" |
| | | width="70%" |
| | | @close="closeDia" |
| | | > |
| | | <el-form |
| | | :model="form" |
| | | label-width="140px" |
| | | label-position="top" |
| | | :rules="rules" |
| | | ref="formRef" |
| | | > |
| | | <el-dialog v-model="dialogFormVisible" |
| | | :title="operationType === 'add' ? 'æ°å¢éè´å°è´¦é¡µé¢' : 'ç¼è¾éè´å°è´¦é¡µé¢'" |
| | | width="70%" |
| | | @close="closeDia"> |
| | | <el-form :model="form" |
| | | label-width="140px" |
| | | label-position="top" |
| | | :rules="rules" |
| | | ref="formRef"> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="éè´ååå·ï¼" prop="purchaseContractNumber"> |
| | | <el-input |
| | | v-model="form.purchaseContractNumber" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | <el-form-item label="éè´ååå·ï¼" |
| | | prop="purchaseContractNumber"> |
| | | <el-input v-model="form.purchaseContractNumber" |
| | | placeholder="请è¾å
¥" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="éå®ååå·ï¼" prop="salesLedgerId"> |
| | | <el-select |
| | | v-model="form.salesLedgerId" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | @change="salesLedgerChange" |
| | | > |
| | | <el-option |
| | | v-for="item in salesContractList" |
| | | :key="item.id" |
| | | :label="item.salesContractNo" |
| | | :value="item.id" |
| | | /> |
| | | <el-form-item label="éå®ååå·ï¼" |
| | | prop="salesLedgerId"> |
| | | <el-select v-model="form.salesLedgerId" |
| | | placeholder="è¯·éæ©" |
| | | filterable |
| | | clearable |
| | | @change="salesLedgerChange"> |
| | | <el-option v-for="item in salesContractList" |
| | | :key="item.id" |
| | | :label="item.salesContractNo" |
| | | :value="item.id" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ä¾åºååç§°ï¼" prop="supplierId"> |
| | | <el-select |
| | | v-model="form.supplierId" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | filterable |
| | | allow-create |
| | | > |
| | | <el-option |
| | | v-for="item in supplierList" |
| | | :key="item.id" |
| | | :label="item.supplierName" |
| | | :value="item.id" |
| | | /> |
| | | <el-form-item label="ä¾åºååç§°ï¼" |
| | | prop="supplierId"> |
| | | <el-select v-model="form.supplierId" |
| | | placeholder="è¯·éæ©" |
| | | filterable |
| | | clearable> |
| | | <el-option v-for="item in supplierList" |
| | | :key="item.id" |
| | | :label="item.supplierName" |
| | | :value="item.id" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="项ç®åç§°ï¼" prop="projectName"> |
| | | <el-input |
| | | v-model="form.projectName" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | <el-form-item label="项ç®åç§°" |
| | | prop="projectName"> |
| | | <el-input v-model="form.projectName" |
| | | placeholder="请è¾å
¥" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="仿¬¾æ¹å¼"> |
| | | <el-input |
| | | v-model="form.paymentMethod" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | <el-input v-model="form.paymentMethod" |
| | | placeholder="请è¾å
¥" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç¾è®¢æ¥æï¼" prop="executionDate"> |
| | | <el-date-picker |
| | | style="width: 100%" |
| | | v-model="form.executionDate" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="date" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | /> |
| | | <el-form-item label="ç¾è®¢æ¥æï¼" |
| | | prop="executionDate"> |
| | | <el-date-picker style="width: 100%" |
| | | v-model="form.executionDate" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="date" |
| | | placeholder="è¯·éæ©" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="审æ¹äººï¼" prop="approverId"> |
| | | <el-select |
| | | v-model="form.approverId" |
| | | placeholder="è¯·éæ©å®¡æ¹äºº" |
| | | clearable |
| | | > |
| | | <el-option |
| | | v-for="item in userList" |
| | | :key="item.userId" |
| | | :label="item.nickName" |
| | | :value="item.userId" |
| | | /> |
| | | <el-form-item label="审æ¹äººï¼" |
| | | prop="approverId"> |
| | | <el-select v-model="form.approverId" |
| | | placeholder="è¯·éæ©å®¡æ¹äºº" |
| | | clearable> |
| | | <el-option v-for="item in userList" |
| | | :key="item.userId" |
| | | :label="item.nickName" |
| | | :value="item.userId" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="å½å
¥äººï¼" prop="recorderId" v-show="false"> |
| | | <el-select |
| | | v-model="form.recorderId" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | disabled |
| | | > |
| | | <el-option |
| | | v-for="item in userList" |
| | | :key="item.userId" |
| | | :label="item.nickName" |
| | | :value="item.userId" |
| | | /> |
| | | <el-form-item label="å½å
¥äººï¼" |
| | | prop="recorderId" |
| | | v-show="false"> |
| | | <el-select v-model="form.recorderId" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | disabled> |
| | | <el-option v-for="item in userList" |
| | | :key="item.userId" |
| | | :label="item.nickName" |
| | | :value="item.userId" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å½å
¥æ¥æï¼" prop="entryDate"> |
| | | <el-date-picker |
| | | style="width: 100%" |
| | | v-model="form.entryDate" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="date" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | /> |
| | | <el-form-item label="å½å
¥æ¥æï¼" |
| | | prop="entryDate"> |
| | | <el-date-picker style="width: 100%" |
| | | v-model="form.entryDate" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="date" |
| | | placeholder="è¯·éæ©" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-form-item label="产åä¿¡æ¯ï¼" prop="entryDate"> |
| | | <el-button type="primary" @click="openProductForm('add')" |
| | | >æ·»å </el-button |
| | | > |
| | | <el-button plain type="danger" @click="deleteProduct" |
| | | >å é¤</el-button |
| | | > |
| | | <el-form-item label="产åä¿¡æ¯ï¼" |
| | | prop="entryDate"> |
| | | <el-button type="primary" |
| | | @click="openProductForm('add')">æ·»å </el-button> |
| | | <el-button plain |
| | | type="danger" |
| | | @click="deleteProduct">å é¤</el-button> |
| | | </el-form-item> |
| | | <div class="select-button-group" style="width: 220px; margin: 20px 0;" v-if="operationType === 'add'"> |
| | | <el-select |
| | | filterable |
| | | allow-create |
| | | :reserve-keyword="true" |
| | | :default-first-option="false" |
| | | v-model="templateName" |
| | | :input-value="filterInputValue" |
| | | @filter-change="onTemplateFilterChange" |
| | | @change="onTemplateChange" |
| | | style="width: 180px; border-right: none; border-radius: 4px 0 0 4px;" |
| | | placeholder="è¯·éæ©" |
| | | class="no-arrow-select" |
| | | > |
| | | <el-option |
| | | v-for="item in templateList" |
| | | :key="item.value" |
| | | :label="item.templateName" |
| | | :value="item.templateName" |
| | | ></el-option> |
| | | <div class="select-button-group" |
| | | style="width: 220px; margin: 20px 0;" |
| | | v-if="operationType === 'add'"> |
| | | <el-select filterable |
| | | allow-create |
| | | :reserve-keyword="true" |
| | | :default-first-option="false" |
| | | v-model="templateName" |
| | | :input-value="filterInputValue" |
| | | @filter-change="onTemplateFilterChange" |
| | | @change="onTemplateChange" |
| | | style="width: 180px; border-right: none; border-radius: 4px 0 0 4px;" |
| | | placeholder="è¯·éæ©" |
| | | class="no-arrow-select"> |
| | | <el-option v-for="item in templateList" |
| | | :key="item.value" |
| | | :label="item.templateName" |
| | | :value="item.templateName"></el-option> |
| | | </el-select> |
| | | <!-- æé®ï¼ä¸ Select é«åº¦å¹é
ï¼å»æå·¦ä¾§è¾¹æ¡ï¼æ ç¼è¡æ¥ --> |
| | | <el-button |
| | | size="small" |
| | | style="height: 32px; border-radius: 0 4px 4px 0; margin-left: -1px;" |
| | | @click="handleButtonClick" |
| | | :disabled="!templateName || templateName.trim() === '' || isTemplateNameDuplicate" |
| | | > |
| | | <el-button size="small" |
| | | style="height: 32px; border-radius: 0 4px 4px 0; margin-left: -1px;" |
| | | @click="handleButtonClick" |
| | | :disabled="!templateName || templateName.trim() === '' || isTemplateNameDuplicate"> |
| | | ä¿å |
| | | </el-button> |
| | | </div> |
| | | </el-row> |
| | | <el-table |
| | | :data="productData" |
| | | border |
| | | @selection-change="productSelected" |
| | | show-summary |
| | | :summary-method="summarizeProTable" |
| | | > |
| | | <el-table-column align="center" type="selection" width="55" /> |
| | | <el-table-column |
| | | align="center" |
| | | label="åºå·" |
| | | type="index" |
| | | width="60" |
| | | /> |
| | | <el-table-column label="产å大类" prop="productCategory" /> |
| | | <el-table-column label="è§æ ¼åå·" prop="specificationModel" /> |
| | | <el-table-column label="åä½" prop="unit" width="70" /> |
| | | <el-table-column label="æ°é" prop="quantity" width="70" /> |
| | | <el-table-column label="åºåé¢è¦æ°é" prop="warnNum" width="120" show-overflow-tooltip /> |
| | | <el-table-column label="ç¨ç(%)" prop="taxRate" width="80" /> |
| | | <el-table-column |
| | | label="å«ç¨åä»·(å
)" |
| | | prop="taxInclusiveUnitPrice" |
| | | :formatter="formattedNumber" |
| | | width="150" |
| | | /> |
| | | <el-table-column |
| | | label="å«ç¨æ»ä»·(å
)" |
| | | prop="taxInclusiveTotalPrice" |
| | | :formatter="formattedNumber" |
| | | width="150" |
| | | /> |
| | | <el-table-column |
| | | label="ä¸å«ç¨æ»ä»·(å
)" |
| | | prop="taxExclusiveTotalPrice" |
| | | :formatter="formattedNumber" |
| | | width="150" |
| | | /> |
| | | <el-table-column |
| | | fixed="right" |
| | | label="æä½" |
| | | min-width="60" |
| | | align="center" |
| | | > |
| | | <el-table :data="productData" |
| | | border |
| | | @selection-change="productSelected" |
| | | show-summary |
| | | :summary-method="summarizeProTable"> |
| | | <el-table-column align="center" |
| | | type="selection" |
| | | width="55" /> |
| | | <el-table-column align="center" |
| | | label="åºå·" |
| | | type="index" |
| | | width="60" /> |
| | | <el-table-column label="产å大类" |
| | | prop="productCategory" /> |
| | | <el-table-column label="è§æ ¼åå·" |
| | | prop="specificationModel" /> |
| | | <el-table-column label="åä½" |
| | | prop="unit" |
| | | width="70" /> |
| | | <el-table-column label="æ°é" |
| | | prop="quantity" |
| | | width="70" /> |
| | | <el-table-column label="åºåé¢è¦æ°é" |
| | | prop="warnNum" |
| | | width="120" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="ç¨ç(%)" |
| | | prop="taxRate" |
| | | width="80" /> |
| | | <el-table-column label="å«ç¨åä»·(å
)" |
| | | prop="taxInclusiveUnitPrice" |
| | | :formatter="formattedNumber" |
| | | width="150" /> |
| | | <el-table-column label="å«ç¨æ»ä»·(å
)" |
| | | prop="taxInclusiveTotalPrice" |
| | | :formatter="formattedNumber" |
| | | width="150" /> |
| | | <el-table-column label="ä¸å«ç¨æ»ä»·(å
)" |
| | | prop="taxExclusiveTotalPrice" |
| | | :formatter="formattedNumber" |
| | | width="150" /> |
| | | <el-table-column label="æ¯å¦è´¨æ£" |
| | | prop="isChecked" |
| | | width="150"> |
| | | <template #default="scope"> |
| | | <el-button |
| | | link |
| | | type="primary" |
| | | size="small" |
| | | @click="openProductForm('edit', scope.row, scope.$index)" |
| | | >ç¼è¾</el-button |
| | | > |
| | | <el-tag :type="scope.row.isChecked ? 'success' : 'info'"> |
| | | {{ scope.row.isChecked ? 'æ¯' : 'å¦' }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column fixed="right" |
| | | label="æä½" |
| | | min-width="60" |
| | | align="center"> |
| | | <template #default="scope"> |
| | | <el-button link |
| | | type="primary" |
| | | size="small" |
| | | @click="openProductForm('edit', scope.row, scope.$index)">ç¼è¾</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="夿³¨Â·ï¼" prop="remark"> |
| | | <el-input |
| | | v-model="form.remark" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | type="textarea" |
| | | :rows="2" |
| | | /> |
| | | <el-form-item label="夿³¨Â·ï¼" |
| | | prop="remark"> |
| | | <el-input v-model="form.remark" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | type="textarea" |
| | | :rows="2" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="éä»¶ææï¼" prop="remark"> |
| | | <el-upload |
| | | v-model:file-list="fileList" |
| | | :action="upload.url" |
| | | multiple |
| | | ref="fileUpload" |
| | | auto-upload |
| | | :headers="upload.headers" |
| | | :before-upload="handleBeforeUpload" |
| | | :on-error="handleUploadError" |
| | | :on-success="handleUploadSuccess" |
| | | :on-remove="handleRemove" |
| | | > |
| | | <el-form-item label="éä»¶ææï¼" |
| | | prop="remark"> |
| | | <el-upload v-model:file-list="fileList" |
| | | :action="upload.url" |
| | | multiple |
| | | ref="fileUpload" |
| | | auto-upload |
| | | :headers="upload.headers" |
| | | :before-upload="handleBeforeUpload" |
| | | :on-error="handleUploadError" |
| | | :on-success="handleUploadSuccess" |
| | | :on-remove="handleRemove"> |
| | | <el-button type="primary">ä¸ä¼ </el-button> |
| | | <template #tip> |
| | | <div class="el-upload__tip"> |
| | |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="submitForm">确认</el-button> |
| | | <el-button type="primary" |
| | | @click="submitForm">确认</el-button> |
| | | <el-button @click="closeDia">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | <el-dialog |
| | | v-model="productFormVisible" |
| | | :title="productOperationType === 'add' ? 'æ°å¢äº§å' : 'ç¼è¾äº§å'" |
| | | width="40%" |
| | | @close="closeProductDia" |
| | | > |
| | | <el-form |
| | | :model="productForm" |
| | | label-width="140px" |
| | | label-position="top" |
| | | :rules="productRules" |
| | | ref="productFormRef" |
| | | > |
| | | <el-dialog v-model="productFormVisible" |
| | | :title="productOperationType === 'add' ? 'æ°å¢äº§å' : 'ç¼è¾äº§å'" |
| | | width="40%" |
| | | @close="closeProductDia"> |
| | | <el-form :model="productForm" |
| | | label-width="140px" |
| | | label-position="top" |
| | | :rules="productRules" |
| | | ref="productFormRef"> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="产å大类ï¼" prop="productId"> |
| | | <el-tree-select |
| | | v-model="productForm.productId" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | check-strictly |
| | | @change="getModels" |
| | | :data="productOptions" |
| | | :render-after-expand="false" |
| | | style="width: 100%" |
| | | /> |
| | | <el-form-item label="产å大类ï¼" |
| | | prop="productId"> |
| | | <el-tree-select v-model="productForm.productId" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | check-strictly |
| | | @change="getModels" |
| | | :data="productOptions" |
| | | :render-after-expand="false" |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="è§æ ¼åå·ï¼" prop="productModelId"> |
| | | <el-select |
| | | v-model="productForm.productModelId" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | @change="getProductModel" |
| | | > |
| | | <el-option |
| | | v-for="item in modelOptions" |
| | | :key="item.id" |
| | | :label="item.model" |
| | | :value="item.id" |
| | | /> |
| | | <el-form-item label="è§æ ¼åå·ï¼" |
| | | prop="productModelId"> |
| | | <el-select v-model="productForm.productModelId" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | @change="getProductModel"> |
| | | <el-option v-for="item in modelOptions" |
| | | :key="item.id" |
| | | :label="item.model" |
| | | :value="item.id" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="åä½ï¼" prop="unit"> |
| | | <el-input |
| | | v-model="productForm.unit" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | <el-form-item label="åä½ï¼" |
| | | prop="unit"> |
| | | <el-input v-model="productForm.unit" |
| | | placeholder="请è¾å
¥" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç¨ç(%)ï¼" prop="taxRate"> |
| | | <el-select |
| | | v-model="productForm.taxRate" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | @change="mathNum" |
| | | > |
| | | <el-option label="1" value="1" /> |
| | | <el-option label="6" value="6" /> |
| | | <el-option label="13" value="13" /> |
| | | <el-form-item label="ç¨ç(%)ï¼" |
| | | prop="taxRate"> |
| | | <el-select v-model="productForm.taxRate" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | @change="mathNum"> |
| | | <el-option label="1" |
| | | value="1" /> |
| | | <el-option label="6" |
| | | value="6" /> |
| | | <el-option label="13" |
| | | value="13" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å«ç¨åä»·(å
)ï¼" prop="taxInclusiveUnitPrice"> |
| | | <el-input-number |
| | | v-model="productForm.taxInclusiveUnitPrice" |
| | | :precision="2" |
| | | :step="0.1" |
| | | clearable |
| | | style="width: 100%" |
| | | @change="mathNum" |
| | | /> |
| | | <el-form-item label="å«ç¨åä»·(å
)ï¼" |
| | | prop="taxInclusiveUnitPrice"> |
| | | <el-input-number v-model="productForm.taxInclusiveUnitPrice" |
| | | :precision="2" |
| | | :step="0.1" |
| | | :min="0" |
| | | clearable |
| | | style="width: 100%" |
| | | @change="mathNum" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ°éï¼" prop="quantity"> |
| | | <el-input-number |
| | | :step="0.1" |
| | | clearable |
| | | :precision="2" |
| | | style="width: 100%" |
| | | v-model="productForm.quantity" |
| | | placeholder="请è¾å
¥" |
| | | @change="mathNum" |
| | | /> |
| | | <el-form-item label="æ°éï¼" |
| | | prop="quantity"> |
| | | <el-input-number :step="0.1" |
| | | clearable |
| | | :precision="2" |
| | | :min="0" |
| | | style="width: 100%" |
| | | v-model="productForm.quantity" |
| | | placeholder="请è¾å
¥" |
| | | @change="mathNum" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å«ç¨æ»ä»·(å
)ï¼" prop="taxInclusiveTotalPrice"> |
| | | <el-input-number |
| | | v-model="productForm.taxInclusiveTotalPrice" |
| | | :precision="2" |
| | | :step="0.1" |
| | | clearable |
| | | style="width: 100%" |
| | | @change="reverseMathNum('taxInclusiveTotalPrice')" |
| | | /> |
| | | <el-form-item label="å«ç¨æ»ä»·(å
)ï¼" |
| | | prop="taxInclusiveTotalPrice"> |
| | | <el-input-number v-model="productForm.taxInclusiveTotalPrice" |
| | | :precision="2" |
| | | :step="0.1" |
| | | :min="0" |
| | | clearable |
| | | style="width: 100%" |
| | | @change="reverseMathNum('taxInclusiveTotalPrice')" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item |
| | | label="ä¸å«ç¨æ»ä»·(å
)ï¼" |
| | | prop="taxExclusiveTotalPrice" |
| | | > |
| | | <el-input |
| | | v-model="productForm.taxExclusiveTotalPrice" |
| | | @change="reverseMathNum('taxExclusiveTotalPrice')" |
| | | /> |
| | | <el-form-item label="ä¸å«ç¨æ»ä»·(å
)ï¼" |
| | | prop="taxExclusiveTotalPrice"> |
| | | <el-input-number v-model="productForm.taxExclusiveTotalPrice" |
| | | :precision="2" |
| | | :step="0.1" |
| | | :min="0" |
| | | clearable |
| | | style="width: 100%" |
| | | @change="reverseMathNum('taxExclusiveTotalPrice')" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å票类åï¼" prop="invoiceType"> |
| | | <el-select |
| | | v-model="productForm.invoiceType" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | > |
| | | <el-option label="墿®ç¥¨" value="墿®ç¥¨" /> |
| | | <el-option label="å¢ä¸ç¥¨" value="å¢ä¸ç¥¨" /> |
| | | <el-form-item label="å票类åï¼" |
| | | prop="invoiceType"> |
| | | <el-select v-model="productForm.invoiceType" |
| | | placeholder="è¯·éæ©" |
| | | clearable> |
| | | <el-option label="墿®ç¥¨" |
| | | value="墿®ç¥¨" /> |
| | | <el-option label="å¢ä¸ç¥¨" |
| | | value="å¢ä¸ç¥¨" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="åºåé¢è¦æ°éï¼" prop="warnNum"> |
| | | <el-input-number |
| | | v-model="productForm.warnNum" |
| | | :precision="2" |
| | | :step="0.1" |
| | | clearable |
| | | style="width: 100%" |
| | | /> |
| | | <el-form-item label="åºåé¢è¦æ°éï¼" |
| | | prop="warnNum"> |
| | | <el-input-number v-model="productForm.warnNum" |
| | | :precision="2" |
| | | :step="0.1" |
| | | :min="0" |
| | | clearable |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ¯å¦è´¨æ£ï¼" |
| | | prop="isChecked"> |
| | | <el-radio-group v-model="productForm.isChecked"> |
| | | <el-radio label="æ¯" |
| | | :value="true" /> |
| | | <el-radio label="å¦" |
| | | :value="false" /> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="submitProduct">确认</el-button> |
| | | <el-button type="primary" |
| | | @click="submitProduct">确认</el-button> |
| | | <el-button @click="closeProductDia">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- äºç»´ç æ¾ç¤ºå¯¹è¯æ¡ --> |
| | | <el-dialog |
| | | v-model="qrCodeDialogVisible" |
| | | title="éè´ååå·äºç»´ç " |
| | | width="400px" |
| | | center |
| | | > |
| | | <el-dialog v-model="qrCodeDialogVisible" |
| | | title="éè´ååå·äºç»´ç " |
| | | width="400px" |
| | | center> |
| | | <div style="text-align: center;"> |
| | | <img :src="qrCodeUrl" alt="äºç»´ç " style="width:200px;height:200px;" /> |
| | | <img :src="qrCodeUrl" |
| | | alt="äºç»´ç " |
| | | style="width:200px;height:200px;" /> |
| | | <div style="margin: 20px;"> |
| | | <el-button type="primary" @click="downloadQRCode">ä¸è½½äºç»´ç å¾ç</el-button> |
| | | <el-button type="primary" |
| | | @click="downloadQRCode">ä¸è½½äºç»´ç å¾ç</el-button> |
| | | </div> |
| | | </div> |
| | | </el-dialog> |
| | | |
| | | <!-- æ«ç æ°å¢å¯¹è¯æ¡ --> |
| | | <el-dialog |
| | | v-model="scanAddDialogVisible" |
| | | title="æ«ç æ°å¢éè´å°è´¦" |
| | | width="70%" |
| | | @close="closeScanAddDialog" |
| | | > |
| | | <el-form |
| | | :model="scanAddForm" |
| | | label-width="140px" |
| | | label-position="top" |
| | | :rules="scanAddRules" |
| | | ref="scanAddFormRef" |
| | | > |
| | | <el-dialog v-model="scanAddDialogVisible" |
| | | title="æ«ç æ°å¢éè´å°è´¦" |
| | | width="70%" |
| | | @close="closeScanAddDialog"> |
| | | <el-form :model="scanAddForm" |
| | | label-width="140px" |
| | | label-position="top" |
| | | :rules="scanAddRules" |
| | | ref="scanAddFormRef"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="æ«ç å
容ï¼"> |
| | | <el-input |
| | | v-model="scanAddForm.scanContent" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="è¯·æ«æäºç»´ç ææå¨è¾å
¥éè´ååä¿¡æ¯" |
| | | @input="parseScanContent" |
| | | /> |
| | | <el-input v-model="scanAddForm.scanContent" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="è¯·æ«æäºç»´ç ææå¨è¾å
¥éè´ååä¿¡æ¯" |
| | | @input="parseScanContent" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="éè´ååå·ï¼" prop="purchaseContractNumber"> |
| | | <el-input |
| | | v-model="scanAddForm.purchaseContractNumber" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | <el-form-item label="éè´ååå·ï¼" |
| | | prop="purchaseContractNumber"> |
| | | <el-input v-model="scanAddForm.purchaseContractNumber" |
| | | placeholder="请è¾å
¥" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ä¾åºååç§°ï¼" prop="supplierName"> |
| | | <el-input |
| | | v-model="scanAddForm.supplierName" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | <el-form-item label="ä¾åºååç§°ï¼" |
| | | prop="supplierName"> |
| | | <el-input v-model="scanAddForm.supplierName" |
| | | placeholder="请è¾å
¥" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="项ç®åç§°ï¼" prop="projectName"> |
| | | <el-input |
| | | v-model="scanAddForm.projectName" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | <el-form-item label="项ç®åç§°ï¼" |
| | | prop="projectName"> |
| | | <el-input v-model="scanAddForm.projectName" |
| | | placeholder="请è¾å
¥" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ååéé¢(å
)ï¼" prop="contractAmount"> |
| | | <el-input-number |
| | | v-model="scanAddForm.contractAmount" |
| | | :precision="2" |
| | | :step="0.1" |
| | | clearable |
| | | style="width: 100%" |
| | | placeholder="请è¾å
¥" |
| | | /> |
| | | <el-form-item label="ååéé¢(å
)ï¼" |
| | | prop="contractAmount"> |
| | | <el-input-number v-model="scanAddForm.contractAmount" |
| | | :precision="2" |
| | | :step="0.1" |
| | | clearable |
| | | style="width: 100%" |
| | | placeholder="请è¾å
¥" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="仿¬¾æ¹å¼ï¼"> |
| | | <el-input |
| | | v-model="scanAddForm.paymentMethod" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | <el-input v-model="scanAddForm.paymentMethod" |
| | | placeholder="请è¾å
¥" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å½å
¥äººï¼"> |
| | | <el-input v-model="scanAddForm.recorderName" disabled /> |
| | | <el-input v-model="scanAddForm.recorderName" |
| | | disabled /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="夿³¨ï¼"> |
| | | <el-input |
| | | v-model="scanAddForm.remark" |
| | | type="textarea" |
| | | :rows="2" |
| | | placeholder="请è¾å
¥å¤æ³¨ä¿¡æ¯" |
| | | clearable |
| | | /> |
| | | <el-input v-model="scanAddForm.remark" |
| | | type="textarea" |
| | | :rows="2" |
| | | placeholder="请è¾å
¥å¤æ³¨ä¿¡æ¯" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="submitScanAdd">确认æ°å¢</el-button> |
| | | <el-button type="primary" |
| | | @click="submitScanAdd">确认æ°å¢</el-button> |
| | | <el-button @click="closeScanAddDialog">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- æ«ç ç»è®°å¯¹è¯æ¡ --> |
| | | <el-dialog |
| | | v-model="scanDialogVisible" |
| | | title="æ«ç ç»è®°" |
| | | width="60%" |
| | | @close="closeScanDialog" |
| | | > |
| | | <el-form |
| | | :model="scanForm" |
| | | label-width="120px" |
| | | label-position="left" |
| | | :rules="scanRules" |
| | | ref="scanFormRef" |
| | | > |
| | | <el-dialog v-model="scanDialogVisible" |
| | | title="æ«ç ç»è®°" |
| | | width="60%" |
| | | @close="closeScanDialog"> |
| | | <el-form :model="scanForm" |
| | | label-width="120px" |
| | | label-position="left" |
| | | :rules="scanRules" |
| | | ref="scanFormRef"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="éè´ååå·ï¼"> |
| | | <el-input v-model="scanForm.purchaseContractNumber" disabled /> |
| | | <el-input v-model="scanForm.purchaseContractNumber" |
| | | disabled /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ä¾åºååç§°ï¼"> |
| | | <el-input v-model="scanForm.supplierName" disabled /> |
| | | <el-input v-model="scanForm.supplierName" |
| | | disabled /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="项ç®åç§°ï¼"> |
| | | <el-input v-model="scanForm.projectName" disabled /> |
| | | <el-input v-model="scanForm.projectName" |
| | | disabled /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ«ç æ¶é´ï¼"> |
| | | <el-input v-model="scanForm.scanTime" disabled /> |
| | | <el-input v-model="scanForm.scanTime" |
| | | disabled /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ«ç 人ï¼"> |
| | | <el-input v-model="scanForm.scannerName" disabled /> |
| | | <el-input v-model="scanForm.scannerName" |
| | | disabled /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="æ«ç 夿³¨ï¼"> |
| | | <el-input |
| | | v-model="scanForm.scanRemark" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请è¾å
¥æ«ç 夿³¨ä¿¡æ¯" |
| | | /> |
| | | <el-input v-model="scanForm.scanRemark" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请è¾å
¥æ«ç 夿³¨ä¿¡æ¯" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="æ«ç è®°å½ï¼"> |
| | | <el-table :data="scanRecords" border style="width: 100%"> |
| | | <el-table-column label="åºå·" type="index" width="60" align="center" /> |
| | | <el-table-column label="æ«ç æ¶é´" prop="scanTime" width="180" /> |
| | | <el-table-column label="æ«ç 人" prop="scannerName" width="120" /> |
| | | <el-table-column label="æ«ç ç¶æ" prop="scanStatus" width="100"> |
| | | <el-table :data="scanRecords" |
| | | border |
| | | style="width: 100%"> |
| | | <el-table-column label="åºå·" |
| | | type="index" |
| | | width="60" |
| | | align="center" /> |
| | | <el-table-column label="æ«ç æ¶é´" |
| | | prop="scanTime" |
| | | width="180" /> |
| | | <el-table-column label="æ«ç 人" |
| | | prop="scannerName" |
| | | width="120" /> |
| | | <el-table-column label="æ«ç ç¶æ" |
| | | prop="scanStatus" |
| | | width="100"> |
| | | <template #default="scope"> |
| | | <el-tag :type="scope.row.scanStatus === 'å·²æ«ç ' ? 'success' : 'warning'"> |
| | | {{ scope.row.scanStatus }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="夿³¨" prop="scanRemark" /> |
| | | <el-table-column label="夿³¨" |
| | | prop="scanRemark" /> |
| | | </el-table> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="submitScan">确认æ«ç </el-button> |
| | | <el-button type="primary" |
| | | @click="submitScan">确认æ«ç </el-button> |
| | | <el-button @click="closeScanDialog">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <FileList ref="fileListRef" /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {getToken} from "@/utils/auth"; |
| | | import pagination from "@/components/PIMTable/Pagination.vue"; |
| | | import {getCurrentInstance, nextTick, onMounted, reactive, ref, toRefs} from "vue"; |
| | | import {Search} from "@element-plus/icons-vue"; |
| | | import {ElMessage, ElMessageBox} from "element-plus"; |
| | | import {userListNoPage} from "@/api/system/user.js"; |
| | | import { |
| | | addOrUpdateSalesLedgerProduct, |
| | | delLedgerFile, |
| | | delProduct, |
| | | getProductInfoByContractNo, |
| | | getSalesLedgerWithProducts, |
| | | } from "@/api/salesManagement/salesLedger.js"; |
| | | import { |
| | | addOrEditPurchase, |
| | | addPurchaseTemplate, |
| | | createPurchaseNo, |
| | | delPurchase, |
| | | getOptions, |
| | | getPurchaseById, |
| | | getPurchaseTemplateList, |
| | | getSalesNo, |
| | | productList, |
| | | purchaseListPage |
| | | } from "@/api/procurementManagement/procurementLedger.js"; |
| | | import useFormData from "@/hooks/useFormData.js"; |
| | | import QRCode from "qrcode"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import {modelList, productTreeList} from "@/api/basicData/product.js"; |
| | | import dayjs from "dayjs"; |
| | | import { getCurrentDate } from "@/utils/index.js"; |
| | | import { getToken } from "@/utils/auth"; |
| | | import pagination from "@/components/PIMTable/Pagination.vue"; |
| | | import { |
| | | ref, |
| | | onMounted, |
| | | reactive, |
| | | toRefs, |
| | | getCurrentInstance, |
| | | nextTick, |
| | | } from "vue"; |
| | | import { Search } from "@element-plus/icons-vue"; |
| | | import { ElMessageBox, ElMessage } from "element-plus"; |
| | | import { userListNoPage } from "@/api/system/user.js"; |
| | | import FileList from "./fileList.vue"; |
| | | import { |
| | | getSalesLedgerWithProducts, |
| | | addOrUpdateSalesLedgerProduct, |
| | | delProduct, |
| | | delLedgerFile, |
| | | getProductInfoByContractNo, |
| | | } from "@/api/salesManagement/salesLedger.js"; |
| | | import { |
| | | addOrEditPurchase, |
| | | addPurchaseTemplate, |
| | | createPurchaseNo, |
| | | delPurchase, |
| | | getSalesNo, |
| | | purchaseListPage, |
| | | productList, |
| | | getPurchaseById, |
| | | getOptions, |
| | | getPurchaseTemplateList, |
| | | } from "@/api/procurementManagement/procurementLedger.js"; |
| | | import useFormData from "@/hooks/useFormData.js"; |
| | | import QRCode from "qrcode"; |
| | | |
| | | const { proxy } = getCurrentInstance(); |
| | | const tableData = ref([]); |
| | | const productData = ref([]); |
| | | const selectedRows = ref([]); |
| | | const productSelectedRows = ref([]); |
| | | const modelOptions = ref([]); |
| | | const userList = ref([]); |
| | | const productOptions = ref([]); |
| | | const salesContractList = ref([]); |
| | | const supplierList = ref([]); |
| | | const tableLoading = ref(false); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | }); |
| | | const total = ref(0); |
| | | const fileList = ref([]); |
| | | const { proxy } = getCurrentInstance(); |
| | | const tableData = ref([]); |
| | | const productData = ref([]); |
| | | const selectedRows = ref([]); |
| | | const productSelectedRows = ref([]); |
| | | const modelOptions = ref([]); |
| | | const userList = ref([]); |
| | | const productOptions = ref([]); |
| | | const salesContractList = ref([]); |
| | | const supplierList = ref([]); |
| | | const tableLoading = ref(false); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | }); |
| | | const total = ref(0); |
| | | const fileList = ref([]); |
| | | import useUserStore from "@/store/modules/user"; |
| | | import { modelList, productTreeList } from "@/api/basicData/product.js"; |
| | | import dayjs from "dayjs"; |
| | | |
| | | const userStore = useUserStore(); |
| | | const userStore = useUserStore(); |
| | | |
| | | // äºç»´ç ç¸å
³åé |
| | | const qrCodeDialogVisible = ref(false); |
| | | const qrCodeUrl = ref(""); |
| | | // äºç»´ç ç¸å
³åé |
| | | const qrCodeDialogVisible = ref(false); |
| | | const qrCodeUrl = ref(""); |
| | | |
| | | // 订å审æ¹ç¶ææ¾ç¤ºææ¬ |
| | | const approvalStatusText = { |
| | | 0: '审æ¹ä¸', |
| | | 1: '审æ¹éè¿', |
| | | 2: '审æ¹å¤±è´¥' |
| | | }; |
| | | // 订å审æ¹ç¶ææ¾ç¤ºææ¬ |
| | | const approvalStatusText = { |
| | | 0: "审æ¹ä¸", |
| | | 1: "审æ¹éè¿", |
| | | 2: "审æ¹å¤±è´¥", |
| | | }; |
| | | |
| | | |
| | | const templateName = ref(''); |
| | | const filterInputValue = ref(''); |
| | | const templateList = ref([]); |
| | | const isTemplateNameDuplicate = ref(false); // æ 记模æ¿åç§°æ¯å¦éå¤ |
| | | |
| | | // æ£æ¥æ¨¡æ¿åç§°æ¯å¦éå¤ |
| | | const checkTemplateNameDuplicate = (name) => { |
| | | if (!name || name.trim() === '') { |
| | | isTemplateNameDuplicate.value = false; |
| | | return false; |
| | | } |
| | | const isDuplicate = templateList.value.some(item => item.templateName === name.trim()); |
| | | isTemplateNameDuplicate.value = isDuplicate; |
| | | return isDuplicate; |
| | | }; |
| | | |
| | | // 鲿宿¶å¨ |
| | | let duplicateCheckTimer = null; |
| | | const onTemplateFilterChange = (val) => { |
| | | filterInputValue.value = val ?? ''; |
| | | // æ¸
é¤ä¹åç宿¶å¨ |
| | | if (duplicateCheckTimer) { |
| | | clearTimeout(duplicateCheckTimer); |
| | | } |
| | | // 宿¶æ£æ¥æ¨¡æ¿åç§°æ¯å¦éå¤ï¼é²æå¤çï¼é¿å
é¢ç¹æç¤ºï¼ |
| | | if (val && val.trim()) { |
| | | duplicateCheckTimer = setTimeout(() => { |
| | | const isDuplicate = checkTemplateNameDuplicate(val); |
| | | if (isDuplicate) { |
| | | ElMessage({ |
| | | message: '模æ¿åç§°å·²åå¨ï¼è¯·æ´æ¢æ¨¡æ¿åç§°', |
| | | type: 'warning', |
| | | duration: 2000 |
| | | }); |
| | | } |
| | | }, 300); // 300ms 鲿 |
| | | } else { |
| | | isTemplateNameDuplicate.value = false; |
| | | } |
| | | }; |
| | | |
| | | // allow-create æ¶ï¼è¾å
¥ä¸åå¨çå
容ä¼ä½ä¸º string å¼è¿åï¼è¿é忥åè¾å
¥æ¡ä»¥ç¡®ä¿æåä¸ä¸¢ |
| | | const onTemplateChange = async (val) => { |
| | | if (typeof val === 'string') { |
| | | filterInputValue.value = val; |
| | | // éæ©æè¾å
¥æ¶æ£æ¥éå¤ |
| | | checkTemplateNameDuplicate(val); |
| | | } |
| | | |
| | | // è¿æ»¤æ°æ®ï¼æ¥æ¾å¹é
çæ¨¡æ¿ |
| | | const matchedTemplate = templateList.value.find(item => item.templateName === val); |
| | | |
| | | if (matchedTemplate?.id) { |
| | | // 妿æ¾å°æ¨¡æ¿ï¼å è½½æ¨¡æ¿æ°æ® |
| | | form.value = { |
| | | ...form.value, |
| | | ...matchedTemplate, |
| | | }; |
| | | productData.value = matchedTemplate.productData || []; |
| | | // çææ°çéè´ååå· |
| | | try { |
| | | const res = await createPurchaseNo(); |
| | | if (res?.data) { |
| | | form.value.purchaseContractNumber = res.data; |
| | | } |
| | | } catch (error) { |
| | | console.error('çæéè´ååå·å¤±è´¥:', error); |
| | | } |
| | | } else { |
| | | // å¦ææ²¡ææ¾å°æ¨¡æ¿ï¼é置表åï¼ä¿æå½å表åç¶æï¼ |
| | | const currentFormData = { ...form.value }; |
| | | const currentProductData = [...productData.value]; |
| | | |
| | | // å¦æå¯¹è¯æ¡æªæå¼ï¼å
æå¼ |
| | | if (!dialogFormVisible.value) { |
| | | operationType.value = 'add'; |
| | | dialogFormVisible.value = true; |
| | | } |
| | | |
| | | // çå¾
ä¸ä¸ä¸ª tick 忢夿°æ® |
| | | await nextTick(); |
| | | form.value = { |
| | | ...form.value, |
| | | ...currentFormData, |
| | | }; |
| | | productData.value = currentProductData; |
| | | } |
| | | }; |
| | | |
| | | // ç¨æ·ä¿¡æ¯è¡¨åå¼¹æ¡æ°æ® |
| | | const operationType = ref(""); |
| | | const dialogFormVisible = ref(false); |
| | | const data = reactive({ |
| | | searchForm: { |
| | | supplierName: "", // ä¾åºååç§° |
| | | purchaseContractNumber: "", // éè´ååç¼å· |
| | | salesContractNo: "", // éå®ååç¼å· |
| | | projectName: "", // 项ç®åç§° |
| | | entryDate: null, // å½å
¥æ¥æ |
| | | entryDateStart: undefined, |
| | | entryDateEnd: undefined, |
| | | }, |
| | | form: { |
| | | purchaseContractNumber: "", |
| | | salesLedgerId: "", |
| | | projectName: "", |
| | | recorderId: "", |
| | | entryDate: "", |
| | | productData: [], |
| | | supplierName: "", |
| | | supplierId: "", |
| | | paymentMethod: "", |
| | | executionDate: "", |
| | | }, |
| | | rules: { |
| | | purchaseContractNumber: [ |
| | | { required: true, message: "请è¾å
¥", trigger: "blur" }, |
| | | ], |
| | | projectName: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | supplierId: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | entryDate: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | approverId:[{ required: true, message: "è¯·éæ©å®¡æ¹äºº", trigger: "change" }], |
| | | executionDate: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | }, |
| | | }); |
| | | const { form, rules } = toRefs(data); |
| | | const { form: searchForm } = useFormData(data.searchForm); |
| | | |
| | | // 产å表åå¼¹æ¡æ°æ® |
| | | const productFormVisible = ref(false); |
| | | const productOperationType = ref(""); |
| | | const productOperationIndex = ref(""); |
| | | const currentId = ref(""); |
| | | const productFormData = reactive({ |
| | | productForm: { |
| | | productId: "", |
| | | productCategory: "", |
| | | productModelId: "", |
| | | specificationModel: "", |
| | | unit: "", |
| | | quantity: "", |
| | | taxInclusiveUnitPrice: "", |
| | | taxRate: "", |
| | | taxInclusiveTotalPrice: "", |
| | | taxExclusiveTotalPrice: "", |
| | | invoiceType: "", |
| | | warnNum: "", |
| | | }, |
| | | productRules: { |
| | | productId: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | productModelId: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | unit: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | quantity: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | taxInclusiveUnitPrice: [ |
| | | { required: true, message: "请è¾å
¥", trigger: "blur" }, |
| | | ], |
| | | taxRate: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | warnNum: [{ required: false, message: "è¯·éæ©", trigger: "change" }], |
| | | taxInclusiveTotalPrice: [ |
| | | { required: true, message: "请è¾å
¥", trigger: "blur" }, |
| | | ], |
| | | taxExclusiveTotalPrice: [ |
| | | { required: true, message: "请è¾å
¥", trigger: "blur" }, |
| | | ], |
| | | invoiceType: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | }, |
| | | }); |
| | | const { productForm, productRules } = toRefs(productFormData); |
| | | const upload = reactive({ |
| | | // ä¸ä¼ çå°å |
| | | url: import.meta.env.VITE_APP_BASE_API + "/file/upload", |
| | | // 设置ä¸ä¼ ç请æ±å¤´é¨ |
| | | headers: { Authorization: "Bearer " + getToken() }, |
| | | }); |
| | | |
| | | const changeDaterange = (value) => { |
| | | if (value) { |
| | | searchForm.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD"); |
| | | searchForm.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD"); |
| | | } else { |
| | | searchForm.entryDateStart = undefined; |
| | | searchForm.entryDateEnd = undefined; |
| | | } |
| | | handleQuery(); |
| | | }; |
| | | |
| | | const formattedNumber = (row, column, cellValue) => { |
| | | if (cellValue === null || cellValue === undefined || cellValue === '') { |
| | | return '0.00'; |
| | | } |
| | | const num = parseFloat(cellValue); |
| | | if (isNaN(num)) { |
| | | return '0.00'; |
| | | } |
| | | return num.toFixed(2); |
| | | }; |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | |
| | | // ä¿åæ¨¡æ¿ |
| | | const handleButtonClick = async () => { |
| | | // æ£æ¥æ¨¡æ¿åç§°æ¯å¦ä¸ºç©º |
| | | if (!templateName.value || templateName.value.trim() === '') { |
| | | ElMessage({ |
| | | message: '请è¾å
¥æ¨¡æ¿åç§°', |
| | | type: 'warning', |
| | | }); |
| | | return; |
| | | } |
| | | const templateName = ref(""); |
| | | const filterInputValue = ref(""); |
| | | const templateList = ref([]); |
| | | const isTemplateNameDuplicate = ref(false); // æ 记模æ¿åç§°æ¯å¦éå¤ |
| | | |
| | | // æ£æ¥æ¨¡æ¿åç§°æ¯å¦éå¤ |
| | | const isDuplicate = checkTemplateNameDuplicate(templateName.value); |
| | | if (isDuplicate) { |
| | | ElMessage({ |
| | | message: '模æ¿åç§°å·²åå¨ï¼è¯·æ´æ¢æ¨¡æ¿åç§°', |
| | | type: 'warning', |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | // æ£æ¥ä¾åºåæ¯å¦éæ© |
| | | if (!form.value.supplierId) { |
| | | ElMessage({ |
| | | message: '请å
éæ©ä¾åºå', |
| | | type: 'warning', |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | // æ£æ¥æ¯å¦æäº§åæ°æ® |
| | | // if (!productData.value || productData.value.length === 0) { |
| | | // ElMessage({ |
| | | // message: '请å
æ·»å 产åä¿¡æ¯', |
| | | // type: 'warning', |
| | | // }); |
| | | // return; |
| | | // } |
| | | |
| | | try { |
| | | let params = { |
| | | productData: proxy.HaveJson(productData.value), |
| | | supplierId: form.value.supplierId, |
| | | paymentMethod: form.value.paymentMethod, |
| | | recorderId: form.value.recorderId, |
| | | approverId: form.value.approverId, |
| | | templateName: templateName.value.trim() |
| | | }; |
| | | console.log(params); |
| | | let res = await addPurchaseTemplate(params); |
| | | |
| | | if (res && res.code === 200) { |
| | | ElMessage({ |
| | | message: '模æ¿ä¿åæå', |
| | | type: 'success', |
| | | }); |
| | | // ä¿åæååéæ°è·å模æ¿å表 |
| | | await getTemplateList(); |
| | | // æ¸
空模æ¿åç§°è¾å
¥ |
| | | templateName.value = ''; |
| | | filterInputValue.value = ''; |
| | | const checkTemplateNameDuplicate = name => { |
| | | if (!name || name.trim() === "") { |
| | | isTemplateNameDuplicate.value = false; |
| | | return false; |
| | | } |
| | | const isDuplicate = templateList.value.some( |
| | | item => item.templateName === name.trim() |
| | | ); |
| | | isTemplateNameDuplicate.value = isDuplicate; |
| | | return isDuplicate; |
| | | }; |
| | | |
| | | // 鲿宿¶å¨ |
| | | let duplicateCheckTimer = null; |
| | | const onTemplateFilterChange = val => { |
| | | filterInputValue.value = val ?? ""; |
| | | // æ¸
é¤ä¹åç宿¶å¨ |
| | | if (duplicateCheckTimer) { |
| | | clearTimeout(duplicateCheckTimer); |
| | | } |
| | | // 宿¶æ£æ¥æ¨¡æ¿åç§°æ¯å¦éå¤ï¼é²æå¤çï¼é¿å
é¢ç¹æç¤ºï¼ |
| | | if (val && val.trim()) { |
| | | duplicateCheckTimer = setTimeout(() => { |
| | | const isDuplicate = checkTemplateNameDuplicate(val); |
| | | if (isDuplicate) { |
| | | ElMessage({ |
| | | message: "模æ¿åç§°å·²åå¨ï¼è¯·æ´æ¢æ¨¡æ¿åç§°", |
| | | type: "warning", |
| | | duration: 2000, |
| | | }); |
| | | } |
| | | }, 300); // 300ms 鲿 |
| | | } else { |
| | | isTemplateNameDuplicate.value = false; |
| | | } |
| | | }; |
| | | |
| | | // allow-create æ¶ï¼è¾å
¥ä¸åå¨çå
容ä¼ä½ä¸º string å¼è¿åï¼è¿é忥åè¾å
¥æ¡ä»¥ç¡®ä¿æåä¸ä¸¢ |
| | | const onTemplateChange = async val => { |
| | | if (typeof val === "string") { |
| | | filterInputValue.value = val; |
| | | // éæ©æè¾å
¥æ¶æ£æ¥éå¤ |
| | | checkTemplateNameDuplicate(val); |
| | | } |
| | | |
| | | // è¿æ»¤æ°æ®ï¼æ¥æ¾å¹é
çæ¨¡æ¿ |
| | | const matchedTemplate = templateList.value.find( |
| | | item => item.templateName === val |
| | | ); |
| | | |
| | | if (matchedTemplate?.id) { |
| | | // 妿æ¾å°æ¨¡æ¿ï¼å è½½æ¨¡æ¿æ°æ® |
| | | form.value = { |
| | | ...form.value, |
| | | ...matchedTemplate, |
| | | }; |
| | | productData.value = matchedTemplate.productData || []; |
| | | // çææ°çéè´ååå· |
| | | try { |
| | | const res = await createPurchaseNo(); |
| | | if (res?.data) { |
| | | form.value.purchaseContractNumber = res.data; |
| | | } |
| | | } catch (error) { |
| | | console.error("çæéè´ååå·å¤±è´¥:", error); |
| | | } |
| | | } else { |
| | | // å¦ææ²¡ææ¾å°æ¨¡æ¿ï¼é置表åï¼ä¿æå½å表åç¶æï¼ |
| | | const currentFormData = { ...form.value }; |
| | | const currentProductData = [...productData.value]; |
| | | |
| | | // å¦æå¯¹è¯æ¡æªæå¼ï¼å
æå¼ |
| | | if (!dialogFormVisible.value) { |
| | | operationType.value = "add"; |
| | | dialogFormVisible.value = true; |
| | | } |
| | | |
| | | // çå¾
ä¸ä¸ä¸ª tick 忢夿°æ® |
| | | await nextTick(); |
| | | form.value = { |
| | | ...form.value, |
| | | ...currentFormData, |
| | | }; |
| | | productData.value = currentProductData; |
| | | } |
| | | }; |
| | | |
| | | // ç¨æ·ä¿¡æ¯è¡¨åå¼¹æ¡æ°æ® |
| | | const operationType = ref(""); |
| | | const dialogFormVisible = ref(false); |
| | | const data = reactive({ |
| | | searchForm: { |
| | | supplierName: "", // ä¾åºååç§° |
| | | purchaseContractNumber: "", // éè´ååç¼å· |
| | | salesContractNo: "", // éå®ååç¼å· |
| | | projectName: "", // 项ç®åç§° |
| | | entryDate: null, // å½å
¥æ¥æ |
| | | entryDateStart: undefined, |
| | | entryDateEnd: undefined, |
| | | }, |
| | | form: { |
| | | purchaseContractNumber: "", |
| | | salesLedgerId: "", |
| | | projectName: "", |
| | | recorderId: "", |
| | | entryDate: "", |
| | | productData: [], |
| | | supplierName: "", |
| | | supplierId: "", |
| | | paymentMethod: "", |
| | | executionDate: "", |
| | | isChecked: true, |
| | | }, |
| | | rules: { |
| | | purchaseContractNumber: [ |
| | | { required: true, message: "请è¾å
¥", trigger: "blur" }, |
| | | ], |
| | | approverId: [ |
| | | { required: true, message: "è¯·éæ©å®¡æ¹äºº", trigger: "change" }, |
| | | ], |
| | | projectName: [ |
| | | { required: true, message: "请è¾å
¥é¡¹ç®åç§°", trigger: "blur" }, |
| | | ], |
| | | supplierId: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | entryDate: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | executionDate: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | }, |
| | | }); |
| | | const { form, rules } = toRefs(data); |
| | | const { form: searchForm } = useFormData({ |
| | | ...data.searchForm, |
| | | // 设置å½å
¥æ¥æèå´ä¸ºå½å¤© |
| | | entryDate: [ |
| | | dayjs().startOf("day").format("YYYY-MM-DD"), |
| | | dayjs().endOf("day").format("YYYY-MM-DD"), |
| | | ], |
| | | entryDateStart: dayjs().startOf("day").format("YYYY-MM-DD"), |
| | | entryDateEnd: dayjs().endOf("day").format("YYYY-MM-DD"), |
| | | }); |
| | | |
| | | // 产å表åå¼¹æ¡æ°æ® |
| | | const productFormVisible = ref(false); |
| | | const productOperationType = ref(""); |
| | | const productOperationIndex = ref(""); |
| | | const currentId = ref(""); |
| | | const productFormData = reactive({ |
| | | productForm: { |
| | | productId: "", |
| | | productCategory: "", |
| | | productModelId: "", |
| | | specificationModel: "", |
| | | unit: "", |
| | | quantity: "", |
| | | taxInclusiveUnitPrice: "", |
| | | taxRate: "", |
| | | taxInclusiveTotalPrice: "", |
| | | taxExclusiveTotalPrice: "", |
| | | invoiceType: "", |
| | | warnNum: "", |
| | | isChecked: true, |
| | | }, |
| | | productRules: { |
| | | productId: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | productModelId: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | unit: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | quantity: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | taxInclusiveUnitPrice: [ |
| | | { required: true, message: "请è¾å
¥", trigger: "blur" }, |
| | | ], |
| | | taxRate: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | warnNum: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | taxInclusiveTotalPrice: [ |
| | | { required: true, message: "请è¾å
¥", trigger: "blur" }, |
| | | ], |
| | | taxExclusiveTotalPrice: [ |
| | | { required: true, message: "请è¾å
¥", trigger: "blur" }, |
| | | ], |
| | | invoiceType: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | isChecked: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | }, |
| | | }); |
| | | const { productForm, productRules } = toRefs(productFormData); |
| | | const upload = reactive({ |
| | | // ä¸ä¼ çå°å |
| | | url: import.meta.env.VITE_APP_BASE_API + "/file/upload", |
| | | // 设置ä¸ä¼ ç请æ±å¤´é¨ |
| | | headers: { Authorization: "Bearer " + getToken() }, |
| | | }); |
| | | |
| | | const changeDaterange = value => { |
| | | if (value) { |
| | | searchForm.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD"); |
| | | searchForm.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD"); |
| | | } else { |
| | | searchForm.entryDateStart = undefined; |
| | | searchForm.entryDateEnd = undefined; |
| | | } |
| | | handleQuery(); |
| | | }; |
| | | |
| | | const formattedNumber = (row, column, cellValue) => { |
| | | return parseFloat(cellValue).toFixed(2); |
| | | }; |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | |
| | | // ä¿åæ¨¡æ¿ |
| | | const handleButtonClick = async () => { |
| | | // æ£æ¥æ¨¡æ¿åç§°æ¯å¦ä¸ºç©º |
| | | if (!templateName.value || templateName.value.trim() === "") { |
| | | ElMessage({ |
| | | message: res?.msg || '模æ¿ä¿å失败', |
| | | type: 'error', |
| | | message: "请è¾å
¥æ¨¡æ¿åç§°", |
| | | type: "warning", |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | // æ£æ¥æ¨¡æ¿åç§°æ¯å¦éå¤ |
| | | const isDuplicate = checkTemplateNameDuplicate(templateName.value); |
| | | if (isDuplicate) { |
| | | ElMessage({ |
| | | message: "模æ¿åç§°å·²åå¨ï¼è¯·æ´æ¢æ¨¡æ¿åç§°", |
| | | type: "warning", |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | // æ£æ¥ä¾åºåæ¯å¦éæ© |
| | | if (!form.value.supplierId) { |
| | | ElMessage({ |
| | | message: "请å
éæ©ä¾åºå", |
| | | type: "warning", |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | // æ£æ¥æ¯å¦æäº§åæ°æ® |
| | | // if (!productData.value || productData.value.length === 0) { |
| | | // ElMessage({ |
| | | // message: '请å
æ·»å 产åä¿¡æ¯', |
| | | // type: 'warning', |
| | | // }); |
| | | // return; |
| | | // } |
| | | |
| | | try { |
| | | let params = { |
| | | productData: proxy.HaveJson(productData.value), |
| | | supplierId: form.value.supplierId, |
| | | paymentMethod: form.value.paymentMethod, |
| | | recorderId: form.value.recorderId, |
| | | approverId: form.value.approverId, |
| | | templateName: templateName.value.trim(), |
| | | }; |
| | | console.log(params); |
| | | let res = await addPurchaseTemplate(params); |
| | | |
| | | if (res && res.code === 200) { |
| | | ElMessage({ |
| | | message: "模æ¿ä¿åæå", |
| | | type: "success", |
| | | }); |
| | | // ä¿åæååéæ°è·å模æ¿å表 |
| | | await getTemplateList(); |
| | | // æ¸
空模æ¿åç§°è¾å
¥ |
| | | templateName.value = ""; |
| | | filterInputValue.value = ""; |
| | | isTemplateNameDuplicate.value = false; |
| | | } else { |
| | | ElMessage({ |
| | | message: res?.msg || "模æ¿ä¿å失败", |
| | | type: "error", |
| | | }); |
| | | } |
| | | } catch (error) { |
| | | console.error("ä¿å模æ¿å¤±è´¥:", error); |
| | | ElMessage({ |
| | | message: "模æ¿ä¿å失败ï¼è¯·ç¨åéè¯", |
| | | type: "error", |
| | | }); |
| | | } |
| | | } catch (error) { |
| | | console.error('ä¿å模æ¿å¤±è´¥:', error); |
| | | ElMessage({ |
| | | message: '模æ¿ä¿å失败ï¼è¯·ç¨åéè¯', |
| | | type: 'error', |
| | | }); |
| | | } |
| | | }; |
| | | // å表åè®¡æ¹æ³ |
| | | const summarizeChildrenTable = (param) => { |
| | | return proxy.summarizeTable( |
| | | }; |
| | | // å表åè®¡æ¹æ³ |
| | | const summarizeChildrenTable = param => { |
| | | return proxy.summarizeTable( |
| | | param, |
| | | [ |
| | | "taxInclusiveUnitPrice", |
| | |
| | | ticketsNum: { noDecimal: true }, // ä¸ä¿çå°æ° |
| | | futureTickets: { noDecimal: true }, // ä¸ä¿çå°æ° |
| | | } |
| | | ); |
| | | }; |
| | | const paginationChange = (obj) => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | const { entryDate, ...rest } = searchForm; |
| | | purchaseListPage({ ...rest, ...page }) |
| | | .then((res) => { |
| | | ); |
| | | }; |
| | | const paginationChange = obj => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | const { entryDate, ...rest } = searchForm; |
| | | purchaseListPage({ ...rest, ...page }) |
| | | .then(res => { |
| | | tableLoading.value = false; |
| | | // tableData.value = res.data.records; |
| | | // å¤çæ°æ®ï¼æ·»å 失æç¶ææ è®° |
| | | tableData.value = res.data.records.map(record => ({ |
| | | ...record, |
| | | isInvalid: record.isWhite === 1 |
| | | isInvalid: record.isWhite === 1, |
| | | })); |
| | | // åå§ååæ°æ®æ°ç» |
| | | tableData.value.forEach((item) => { |
| | | tableData.value.forEach(item => { |
| | | item.children = []; |
| | | }); |
| | | total.value = res.data.total; |
| | |
| | | .catch(() => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = (selection) => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | const productSelected = (selectedRows) => { |
| | | productSelectedRows.value = selectedRows; |
| | | }; |
| | | const expandedRowKeys = ref([]); |
| | | // å±å¼è¡ |
| | | const expandChange = async (row, expandedRows) => { |
| | | if (expandedRows.length > 0) { |
| | | expandedRowKeys.value = []; |
| | | try { |
| | | const res = await productList({ salesLedgerId: row.id, type: 2 }); |
| | | const index = tableData.value.findIndex((item) => item.id === row.id); |
| | | if (index > -1) { |
| | | tableData.value[index].children = res.data || []; |
| | | expandedRowKeys.value.push(row.id); |
| | | } |
| | | } catch (error) { |
| | | console.error('å 载产åå表失败:', error); |
| | | proxy.$modal.msgError('å 载产åå表失败'); |
| | | // å±å¼å¤±è´¥æ¶ï¼ç§»é¤å±å¼ç¶æ |
| | | const index = expandedRows.findIndex(item => item.id === row.id); |
| | | if (index > -1) { |
| | | expandedRows.splice(index, 1); |
| | | } |
| | | } |
| | | } else { |
| | | expandedRowKeys.value = []; |
| | | } |
| | | }; |
| | | // 主表åè®¡æ¹æ³ |
| | | const summarizeMainTable = (param) => { |
| | | return proxy.summarizeTable(param, ["contractAmount"]); |
| | | }; |
| | | // å表åè®¡æ¹æ³ |
| | | const summarizeProTable = (param) => { |
| | | return proxy.summarizeTable(param, [ |
| | | "taxInclusiveUnitPrice", |
| | | "taxInclusiveTotalPrice", |
| | | "taxExclusiveTotalPrice", |
| | | ]); |
| | | }; |
| | | // æå¼å¼¹æ¡ |
| | | const openForm = async (type, row) => { |
| | | await getTemplateList() |
| | | operationType.value = type; |
| | | form.value = {}; |
| | | productData.value = []; |
| | | fileList.value = []; |
| | | templateName.value = ''; |
| | | filterInputValue.value = ''; |
| | | isTemplateNameDuplicate.value = false; |
| | | try { |
| | | // å¹¶è¡å è½½åºç¡æ°æ® |
| | | const [userRes, salesRes, supplierRes] = await Promise.all([ |
| | | userListNoPage(), |
| | | getSalesNo(), |
| | | getOptions() |
| | | ]); |
| | | |
| | | userList.value = userRes.data || []; |
| | | salesContractList.value = salesRes || []; |
| | | // ä¾åºåè¿æ»¤åºisWhite=0 çæ°æ® |
| | | supplierList.value = (supplierRes.data || []).filter((item) => item.isWhite === 0); |
| | | |
| | | // 设置é»è®¤å¼ |
| | | form.value.recorderId = userStore.id; |
| | | form.value.entryDate = getCurrentDate(); |
| | | |
| | | if (type === "add") { |
| | | // æ°å¢æ¶çæéè´ååå· |
| | | }; |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = selection => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | const productSelected = selectedRows => { |
| | | productSelectedRows.value = selectedRows; |
| | | }; |
| | | const expandedRowKeys = ref([]); |
| | | // å±å¼è¡ |
| | | const expandChange = async (row, expandedRows) => { |
| | | if (expandedRows.length > 0) { |
| | | expandedRowKeys.value = []; |
| | | try { |
| | | const purchaseNoRes = await createPurchaseNo(); |
| | | if (purchaseNoRes?.data) { |
| | | form.value.purchaseContractNumber = purchaseNoRes.data; |
| | | const res = await productList({ salesLedgerId: row.id, type: 2 }); |
| | | const index = tableData.value.findIndex(item => item.id === row.id); |
| | | if (index > -1) { |
| | | tableData.value[index].children = res.data || []; |
| | | expandedRowKeys.value.push(row.id); |
| | | } |
| | | } catch (error) { |
| | | console.error('çæéè´ååå·å¤±è´¥:', error); |
| | | proxy.$modal.msgWarning('çæéè´ååå·å¤±è´¥'); |
| | | console.error("å 载产åå表失败:", error); |
| | | proxy.$modal.msgError("å 载产åå表失败"); |
| | | // å±å¼å¤±è´¥æ¶ï¼ç§»é¤å±å¼ç¶æ |
| | | const index = expandedRows.findIndex(item => item.id === row.id); |
| | | if (index > -1) { |
| | | expandedRows.splice(index, 1); |
| | | } |
| | | } |
| | | } else if (type === "edit" && row?.id) { |
| | | // ç¼è¾æ¶å è½½æ°æ® |
| | | currentId.value = row.id; |
| | | try { |
| | | const purchaseRes = await getPurchaseById({ id: row.id, type: 2 }); |
| | | form.value = { ...purchaseRes }; |
| | | productData.value = purchaseRes.productData || []; |
| | | fileList.value = purchaseRes.salesLedgerFiles || []; |
| | | } catch (error) { |
| | | console.error('å è½½éè´å°è´¦æ°æ®å¤±è´¥:', error); |
| | | proxy.$modal.msgError('å è½½æ°æ®å¤±è´¥'); |
| | | return; |
| | | } |
| | | } |
| | | |
| | | dialogFormVisible.value = true; |
| | | } catch (error) { |
| | | console.error('æå¼è¡¨å失败:', error); |
| | | proxy.$modal.msgError('å è½½åºç¡æ°æ®å¤±è´¥'); |
| | | } |
| | | }; |
| | | // ä¸ä¼ åæ ¡æ£ |
| | | function handleBeforeUpload(file) { |
| | | // æ ¡æ£æä»¶å¤§å° |
| | | if (file.size > 1024 * 1024 * 10) { |
| | | proxy.$modal.msgError("ä¸ä¼ æä»¶å¤§å°ä¸è½è¶
è¿10MB!"); |
| | | return false; |
| | | } |
| | | 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; |
| | | proxy.$modal.msgSuccess("ä¸ä¼ æå"); |
| | | } else { |
| | | proxy.$modal.msgError(res.msg); |
| | | proxy.$refs.fileUpload.handleRemove(file); |
| | | } |
| | | } |
| | | // ç§»é¤æä»¶ |
| | | async function handleRemove(file) { |
| | | if (!file?.id) { |
| | | return; |
| | | } |
| | | |
| | | if (file.size > 1024 * 1024 * 10) { |
| | | // ä»
å端æ¸
çï¼ä¸è°ç¨å 餿¥å£åæç¤º |
| | | return; |
| | | } |
| | | |
| | | if (operationType.value === "edit" && file.id) { |
| | | try { |
| | | await delLedgerFile([file.id]); |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | } catch (error) { |
| | | console.error('å é¤æä»¶å¤±è´¥:', error); |
| | | proxy.$modal.msgError("å é¤æä»¶å¤±è´¥"); |
| | | } |
| | | } |
| | | } |
| | | // æäº¤è¡¨å |
| | | const submitForm = async () => { |
| | | try { |
| | | const valid = await proxy.$refs["formRef"].validate().catch(() => false); |
| | | if (!valid) { |
| | | return; |
| | | } |
| | | |
| | | if (!productData.value || productData.value.length === 0) { |
| | | proxy.$modal.msgWarning("请添å 产åä¿¡æ¯"); |
| | | return; |
| | | } |
| | | |
| | | form.value.productData = proxy.HaveJson(productData.value); |
| | | form.value.tempFileIds = fileList.value |
| | | .filter(item => item.tempId) |
| | | .map((item) => item.tempId); |
| | | form.value.type = 2; |
| | | |
| | | try { |
| | | await addOrEditPurchase(form.value); |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeDia(); |
| | | getList(); |
| | | } catch (error) { |
| | | console.error('æäº¤è¡¨å失败:', error); |
| | | proxy.$modal.msgError("æäº¤å¤±è´¥ï¼è¯·ç¨åéè¯"); |
| | | } |
| | | } catch (error) { |
| | | console.error('表åéªè¯å¤±è´¥:', error); |
| | | } |
| | | }; |
| | | // å
³éå¼¹æ¡ |
| | | const closeDia = () => { |
| | | proxy.resetForm("formRef"); |
| | | dialogFormVisible.value = false; |
| | | }; |
| | | // æå¼äº§åå¼¹æ¡ |
| | | const openProductForm = (type, row, index) => { |
| | | productOperationType.value = type; |
| | | productOperationIndex.value = index; |
| | | productForm.value = {}; |
| | | proxy.resetForm("productFormRef"); |
| | | if (type === "edit") { |
| | | productForm.value = { ...row }; |
| | | } |
| | | productFormVisible.value = true; |
| | | getProductOptions(); |
| | | }; |
| | | const getProductOptions = async () => { |
| | | try { |
| | | const res = await productTreeList(); |
| | | productOptions.value = convertIdToValue(res); |
| | | } catch (error) { |
| | | console.error('å 载产åé项失败:', error); |
| | | proxy.$modal.msgError('å 载产åé项失败'); |
| | | } |
| | | }; |
| | | const getModels = async (value) => { |
| | | if (value) { |
| | | productForm.value.productCategory = findNodeById(productOptions.value, value) || ""; |
| | | try { |
| | | const res = await modelList({ id: value }); |
| | | modelOptions.value = res || []; |
| | | } catch (error) { |
| | | console.error('å è½½è§æ ¼åå·å¤±è´¥:', error); |
| | | proxy.$modal.msgError('å è½½è§æ ¼åå·å¤±è´¥'); |
| | | modelOptions.value = []; |
| | | } |
| | | } else { |
| | | productForm.value.productCategory = ""; |
| | | modelOptions.value = []; |
| | | } |
| | | }; |
| | | const getProductModel = (value) => { |
| | | const index = modelOptions.value.findIndex((item) => item.id === value); |
| | | if (index !== -1) { |
| | | productForm.value.specificationModel = modelOptions.value[index].model; |
| | | productForm.value.unit = modelOptions.value[index].unit; |
| | | } else { |
| | | productForm.value.specificationModel = null; |
| | | productForm.value.unit = null; |
| | | } |
| | | }; |
| | | const findNodeById = (nodes, productId) => { |
| | | for (let i = 0; i < nodes.length; i++) { |
| | | if (nodes[i].value === productId) { |
| | | return nodes[i].label; // æ¾å°èç¹ï¼è¿å该èç¹çlabel |
| | | } |
| | | if (nodes[i].children && nodes[i].children.length > 0) { |
| | | const foundNode = findNodeById(nodes[i].children, productId); |
| | | if (foundNode) { |
| | | return foundNode; // å¨åèç¹ä¸æ¾å°ï¼ç´æ¥è¿åï¼å·²ç»æ¯labelåç¬¦ä¸²ï¼ |
| | | } |
| | | } |
| | | } |
| | | return null; // æ²¡ææ¾å°èç¹ï¼è¿ånull |
| | | }; |
| | | function convertIdToValue(data) { |
| | | return data.map((item) => { |
| | | const { id, children, ...rest } = item; |
| | | const newItem = { |
| | | ...rest, |
| | | value: id, // å° id æ¹ä¸º value |
| | | }; |
| | | if (children && children.length > 0) { |
| | | newItem.children = convertIdToValue(children); |
| | | } |
| | | |
| | | return newItem; |
| | | }); |
| | | } |
| | | // æäº¤äº§å表å |
| | | const submitProduct = async () => { |
| | | try { |
| | | const valid = await proxy.$refs["productFormRef"].validate().catch(() => false); |
| | | if (!valid) { |
| | | return; |
| | | } |
| | | |
| | | if (operationType.value === "edit") { |
| | | await submitProductEdit(); |
| | | } else { |
| | | if (productOperationType.value === "add") { |
| | | productData.value.push({ ...productForm.value }); |
| | | } else { |
| | | productData.value[productOperationIndex.value] = { |
| | | ...productForm.value, |
| | | }; |
| | | } |
| | | closeProductDia(); |
| | | expandedRowKeys.value = []; |
| | | } |
| | | } catch (error) { |
| | | console.error('æäº¤äº§å表å失败:', error); |
| | | } |
| | | }; |
| | | |
| | | const submitProductEdit = async () => { |
| | | try { |
| | | productForm.value.salesLedgerId = currentId.value; |
| | | productForm.value.type = 2; |
| | | await addOrUpdateSalesLedgerProduct(productForm.value); |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeProductDia(); |
| | | |
| | | // éæ°å è½½äº§åæ°æ® |
| | | }; |
| | | // 主表åè®¡æ¹æ³ |
| | | const summarizeMainTable = param => { |
| | | return proxy.summarizeTable(param, ["contractAmount"]); |
| | | }; |
| | | // å表åè®¡æ¹æ³ |
| | | const summarizeProTable = param => { |
| | | return proxy.summarizeTable(param, [ |
| | | "taxInclusiveUnitPrice", |
| | | "taxInclusiveTotalPrice", |
| | | "taxExclusiveTotalPrice", |
| | | ]); |
| | | }; |
| | | // æå¼å¼¹æ¡ |
| | | const openForm = async (type, row) => { |
| | | await getTemplateList(); |
| | | operationType.value = type; |
| | | form.value = {}; |
| | | productData.value = []; |
| | | fileList.value = []; |
| | | templateName.value = ""; |
| | | filterInputValue.value = ""; |
| | | isTemplateNameDuplicate.value = false; |
| | | try { |
| | | const res = await getPurchaseById({ id: currentId.value, type: 2 }); |
| | | productData.value = res.productData || []; |
| | | } catch (error) { |
| | | console.error('éæ°å è½½äº§åæ°æ®å¤±è´¥:', error); |
| | | } |
| | | } catch (error) { |
| | | console.error('æäº¤äº§åç¼è¾å¤±è´¥:', error); |
| | | proxy.$modal.msgError("æäº¤å¤±è´¥ï¼è¯·ç¨åéè¯"); |
| | | } |
| | | }; |
| | | // å é¤äº§å |
| | | const deleteProduct = async () => { |
| | | if (productSelectedRows.value.length === 0) { |
| | | proxy.$modal.msgWarning("è¯·éæ©æ°æ®"); |
| | | return; |
| | | } |
| | | |
| | | if (operationType.value === "add") { |
| | | // æ°å¢æ¨¡å¼ä¸ï¼ç´æ¥ä»åç«¯æ°æ®ä¸å é¤ |
| | | productSelectedRows.value.forEach((selectedRow) => { |
| | | const index = productData.value.findIndex( |
| | | (product) => product.id === selectedRow.id |
| | | // å¹¶è¡å è½½åºç¡æ°æ® |
| | | const [userRes, salesRes, supplierRes] = await Promise.all([ |
| | | userListNoPage(), |
| | | getSalesNo(), |
| | | getOptions(), |
| | | ]); |
| | | |
| | | userList.value = userRes.data || []; |
| | | salesContractList.value = salesRes || []; |
| | | // ä¾åºåè¿æ»¤åºisWhite=0 çæ°æ® |
| | | supplierList.value = (supplierRes.data || []).filter( |
| | | item => item.isWhite === 0 |
| | | ); |
| | | if (index !== -1) { |
| | | productData.value.splice(index, 1); |
| | | |
| | | // 设置é»è®¤å¼ |
| | | form.value.recorderId = userStore.id; |
| | | form.value.entryDate = getCurrentDate(); |
| | | |
| | | if (type === "add") { |
| | | // æ°å¢æ¶çæéè´ååå· |
| | | try { |
| | | const purchaseNoRes = await createPurchaseNo(); |
| | | if (purchaseNoRes?.data) { |
| | | form.value.purchaseContractNumber = purchaseNoRes.data; |
| | | } |
| | | } catch (error) { |
| | | console.error("çæéè´ååå·å¤±è´¥:", error); |
| | | proxy.$modal.msgWarning("çæéè´ååå·å¤±è´¥"); |
| | | } |
| | | } else if (type === "edit" && row?.id) { |
| | | // ç¼è¾æ¶å è½½æ°æ® |
| | | currentId.value = row.id; |
| | | try { |
| | | const purchaseRes = await getPurchaseById({ id: row.id, type: 2 }); |
| | | form.value = { ...purchaseRes }; |
| | | productData.value = purchaseRes.productData || []; |
| | | fileList.value = purchaseRes.salesLedgerFiles || []; |
| | | } catch (error) { |
| | | console.error("å è½½éè´å°è´¦æ°æ®å¤±è´¥:", error); |
| | | proxy.$modal.msgError("å è½½æ°æ®å¤±è´¥"); |
| | | return; |
| | | } |
| | | } |
| | | |
| | | if (form.value.salesLedgerId == -1) { |
| | | form.value.salesLedgerId = null; |
| | | } |
| | | console.log(form.value, "form.value==========="); |
| | | dialogFormVisible.value = true; |
| | | } catch (error) { |
| | | console.error("æå¼è¡¨å失败:", error); |
| | | proxy.$modal.msgError("å è½½åºç¡æ°æ®å¤±è´¥"); |
| | | } |
| | | }; |
| | | // ä¸ä¼ åæ ¡æ£ |
| | | function handleBeforeUpload(file) { |
| | | // æ ¡æ£æä»¶å¤§å° |
| | | if (file.size > 1024 * 1024 * 10) { |
| | | proxy.$modal.msgError("ä¸ä¼ æä»¶å¤§å°ä¸è½è¶
è¿10MB!"); |
| | | return false; |
| | | } |
| | | 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; |
| | | proxy.$modal.msgSuccess("ä¸ä¼ æå"); |
| | | } else { |
| | | proxy.$modal.msgError(res.msg); |
| | | proxy.$refs.fileUpload.handleRemove(file); |
| | | } |
| | | } |
| | | // ç§»é¤æä»¶ |
| | | async function handleRemove(file) { |
| | | if (!file?.id) { |
| | | return; |
| | | } |
| | | console.log("handleRemove", file.id); |
| | | if (file.size > 1024 * 1024 * 10) { |
| | | // ä»
å端æ¸
çï¼ä¸è°ç¨å 餿¥å£åæç¤º |
| | | return; |
| | | } |
| | | |
| | | if (operationType.value === "edit" && file.id) { |
| | | try { |
| | | await delLedgerFile([file.id]); |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | } catch (error) { |
| | | console.error("å é¤æä»¶å¤±è´¥:", error); |
| | | proxy.$modal.msgError("å é¤æä»¶å¤±è´¥"); |
| | | } |
| | | } |
| | | } |
| | | // æäº¤è¡¨å |
| | | const submitForm = () => { |
| | | proxy.$refs["formRef"].validate(valid => { |
| | | if (valid) { |
| | | if (productData.value.length > 0) { |
| | | form.value.productData = proxy.HaveJson(productData.value); |
| | | } else { |
| | | proxy.$modal.msgWarning("请添å 产åä¿¡æ¯"); |
| | | return; |
| | | } |
| | | let tempFileIds = []; |
| | | if (fileList.value.length > 0) { |
| | | tempFileIds = fileList.value.map(item => item.tempId); |
| | | } |
| | | form.value.tempFileIds = tempFileIds; |
| | | form.value.type = 2; |
| | | |
| | | // 妿salesLedgerId为空ï¼åä¸ä¼ ésalesContractNo |
| | | if (!form.value.salesLedgerId) { |
| | | form.value.salesContractNo = ""; |
| | | } |
| | | |
| | | addOrEditPurchase(form.value).then(res => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeDia(); |
| | | getList(); |
| | | }); |
| | | } |
| | | }); |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | } else { |
| | | // ç¼è¾æ¨¡å¼ä¸ï¼éè¦è°ç¨æ¥å£å é¤ |
| | | const ids = productSelectedRows.value |
| | | .filter(item => item.id) |
| | | .map((item) => item.id); |
| | | |
| | | if (ids.length === 0) { |
| | | proxy.$modal.msgWarning("è¯·éæ©ææçæ°æ®"); |
| | | }; |
| | | // å
³éå¼¹æ¡ |
| | | const closeDia = () => { |
| | | proxy.resetForm("formRef"); |
| | | dialogFormVisible.value = false; |
| | | }; |
| | | // æå¼äº§åå¼¹æ¡ |
| | | const openProductForm = (type, row, index) => { |
| | | productOperationType.value = type; |
| | | productOperationIndex.value = index; |
| | | productForm.value = {}; |
| | | proxy.resetForm("productFormRef"); |
| | | if (type === "edit") { |
| | | productForm.value = { ...row }; |
| | | } |
| | | productFormVisible.value = true; |
| | | getProductOptions(); |
| | | }; |
| | | const getProductOptions = () => { |
| | | productTreeList().then(res => { |
| | | productOptions.value = convertIdToValue(res); |
| | | }); |
| | | }; |
| | | const getModels = value => { |
| | | if (value) { |
| | | productForm.value.productCategory = |
| | | findNodeById(productOptions.value, value) || ""; |
| | | modelList({ id: value }).then(res => { |
| | | modelOptions.value = res; |
| | | }); |
| | | } else { |
| | | productForm.value.productCategory = ""; |
| | | modelOptions.value = []; |
| | | } |
| | | }; |
| | | const getProductModel = value => { |
| | | const index = modelOptions.value.findIndex(item => item.id === value); |
| | | if (index !== -1) { |
| | | productForm.value.specificationModel = modelOptions.value[index].model; |
| | | productForm.value.unit = modelOptions.value[index].unit; |
| | | } else { |
| | | productForm.value.specificationModel = null; |
| | | productForm.value.unit = null; |
| | | } |
| | | }; |
| | | const findNodeById = (nodes, productId) => { |
| | | for (let i = 0; i < nodes.length; i++) { |
| | | if (nodes[i].value === productId) { |
| | | return nodes[i].label; // æ¾å°èç¹ï¼è¿å该èç¹çlabel |
| | | } |
| | | if (nodes[i].children && nodes[i].children.length > 0) { |
| | | const foundNode = findNodeById(nodes[i].children, productId); |
| | | if (foundNode) { |
| | | return foundNode; // å¨åèç¹ä¸æ¾å°ï¼ç´æ¥è¿åï¼å·²ç»æ¯labelåç¬¦ä¸²ï¼ |
| | | } |
| | | } |
| | | } |
| | | return null; // æ²¡ææ¾å°èç¹ï¼è¿ånull |
| | | }; |
| | | function convertIdToValue(data) { |
| | | return data.map(item => { |
| | | const { id, children, ...rest } = item; |
| | | const newItem = { |
| | | ...rest, |
| | | value: id, // å° id æ¹ä¸º value |
| | | }; |
| | | if (children && children.length > 0) { |
| | | newItem.children = convertIdToValue(children); |
| | | } |
| | | |
| | | return newItem; |
| | | }); |
| | | } |
| | | // æäº¤äº§å表å |
| | | const submitProduct = () => { |
| | | proxy.$refs["productFormRef"].validate(valid => { |
| | | if (valid) { |
| | | if (operationType.value === "edit") { |
| | | submitProductEdit(); |
| | | } else { |
| | | if (productOperationType.value === "add") { |
| | | productData.value.push({ ...productForm.value }); |
| | | console.log("productData.value---", productData.value); |
| | | } else { |
| | | productData.value[productOperationIndex.value] = { |
| | | ...productForm.value, |
| | | }; |
| | | } |
| | | closeProductDia(); |
| | | } |
| | | } |
| | | }); |
| | | }; |
| | | const submitProductEdit = () => { |
| | | productForm.value.salesLedgerId = currentId.value; |
| | | productForm.value.type = 2; |
| | | addOrUpdateSalesLedgerProduct(productForm.value).then(res => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeProductDia(); |
| | | getPurchaseById({ id: currentId.value, type: 2 }).then(res => { |
| | | productData.value = res.productData; |
| | | }); |
| | | }); |
| | | }; |
| | | // å é¤äº§å |
| | | const deleteProduct = () => { |
| | | if (productSelectedRows.value.length === 0) { |
| | | proxy.$modal.msgWarning("è¯·éæ©æ°æ®"); |
| | | return; |
| | | } |
| | | |
| | | try { |
| | | await ElMessageBox.confirm("éä¸çå
容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼", "å é¤ç¡®è®¤", { |
| | | if (operationType.value === "add") { |
| | | productSelectedRows.value.forEach(selectedRow => { |
| | | const index = productData.value.findIndex( |
| | | product => product.id === selectedRow.id |
| | | ); |
| | | if (index !== -1) { |
| | | productData.value.splice(index, 1); |
| | | } |
| | | }); |
| | | } else { |
| | | let ids = []; |
| | | if (productSelectedRows.value.length > 0) { |
| | | ids = productSelectedRows.value.map(item => item.id); |
| | | } |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | delProduct(ids).then(res => { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | closeProductDia(); |
| | | getSalesLedgerWithProducts({ id: currentId.value, type: 2 }).then( |
| | | res => { |
| | | productData.value = res.productData; |
| | | } |
| | | ); |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | } |
| | | }; |
| | | // å
³é产åå¼¹æ¡ |
| | | const closeProductDia = () => { |
| | | proxy.resetForm("productFormRef"); |
| | | productFormVisible.value = false; |
| | | }; |
| | | // å¯¼åº |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | proxy.download("/purchase/ledger/export", {}, "éè´å°è´¦.xlsx"); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | |
| | | await delProduct(ids); |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | closeProductDia(); |
| | | |
| | | // éæ°å è½½äº§åæ°æ® |
| | | try { |
| | | const res = await getSalesLedgerWithProducts({ id: currentId.value, type: 2 }); |
| | | productData.value = res.productData || []; |
| | | } catch (error) { |
| | | console.error('éæ°å è½½äº§åæ°æ®å¤±è´¥:', error); |
| | | } |
| | | } catch (error) { |
| | | if (error !== 'cancel') { |
| | | console.error('å é¤äº§å失败:', error); |
| | | proxy.$modal.msgError("å é¤å¤±è´¥ï¼è¯·ç¨åéè¯"); |
| | | } |
| | | } |
| | | } |
| | | }; |
| | | // å
³é产åå¼¹æ¡ |
| | | const closeProductDia = () => { |
| | | proxy.resetForm("productFormRef"); |
| | | productFormVisible.value = false; |
| | | }; |
| | | // å¯¼åº |
| | | const handleOut = async () => { |
| | | try { |
| | | await ElMessageBox.confirm("éä¸çå
容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åºç¡®è®¤", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }); |
| | | proxy.download("/purchase/ledger/export", {}, "éè´å°è´¦.xlsx"); |
| | | } catch (error) { |
| | | if (error !== 'cancel') { |
| | | console.error('导åºå¤±è´¥:', error); |
| | | proxy.$modal.msgError("导åºå¤±è´¥ï¼è¯·ç¨åéè¯"); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // å é¤ |
| | | const handleDelete = async () => { |
| | | if (selectedRows.value.length === 0) { |
| | | proxy.$modal.msgWarning("è¯·éæ©æ°æ®"); |
| | | return; |
| | | } |
| | | |
| | | // æ£æ¥æ¯å¦æä»äººç»´æ¤çæ°æ® |
| | | const unauthorizedData = selectedRows.value.filter(item => item.recorderName !== userStore.nickName); |
| | | if (unauthorizedData.length > 0) { |
| | | proxy.$modal.msgWarning("ä¸å¯å é¤ä»äººç»´æ¤çæ°æ®"); |
| | | return; |
| | | } |
| | | |
| | | const ids = selectedRows.value |
| | | .filter(item => item.id) |
| | | .map((item) => item.id); |
| | | |
| | | if (ids.length === 0) { |
| | | proxy.$modal.msgWarning("è¯·éæ©ææçæ°æ®"); |
| | | return; |
| | | } |
| | | |
| | | try { |
| | | await ElMessageBox.confirm("éä¸çå
容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼", "å é¤ç¡®è®¤", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }); |
| | | |
| | | await delPurchase(ids); |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | getList(); |
| | | } catch (error) { |
| | | if (error !== 'cancel') { |
| | | console.error('å é¤å¤±è´¥:', error); |
| | | proxy.$modal.msgError("å é¤å¤±è´¥ï¼è¯·ç¨åéè¯"); |
| | | } |
| | | } |
| | | }; |
| | | const mathNum = () => { |
| | | if (!productForm.value.taxRate) { |
| | | proxy.$modal.msgWarning("请å
éæ©ç¨ç"); |
| | | return; |
| | | } |
| | | if (!productForm.value.taxInclusiveUnitPrice) { |
| | | return; |
| | | } |
| | | if (!productForm.value.quantity) { |
| | | return; |
| | | } |
| | | // å«ç¨æ»ä»·è®¡ç® |
| | | productForm.value.taxInclusiveTotalPrice = |
| | | proxy.calculateTaxIncludeTotalPrice( |
| | | productForm.value.taxInclusiveUnitPrice, |
| | | productForm.value.quantity |
| | | }; |
| | | // å é¤ |
| | | const handleDelete = () => { |
| | | let ids = []; |
| | | if (selectedRows.value.length > 0) { |
| | | // æ£æ¥æ¯å¦æä»äººç»´æ¤çæ°æ® |
| | | const unauthorizedData = selectedRows.value.filter( |
| | | item => item.recorderName !== userStore.nickName |
| | | ); |
| | | if (productForm.value.taxRate) { |
| | | // ä¸å«ç¨æ»ä»·è®¡ç® |
| | | productForm.value.taxExclusiveTotalPrice = |
| | | proxy.calculateTaxExclusiveTotalPrice( |
| | | productForm.value.taxInclusiveTotalPrice, |
| | | productForm.value.taxRate |
| | | ); |
| | | } |
| | | }; |
| | | const reverseMathNum = (field) => { |
| | | if (!productForm.value.taxRate) { |
| | | proxy.$modal.msgWarning("请å
éæ©ç¨ç"); |
| | | return; |
| | | } |
| | | const taxRate = Number(productForm.value.taxRate); |
| | | if (!taxRate) return; |
| | | if (field === 'taxInclusiveTotalPrice') { |
| | | // å·²ç¥å«ç¨æ»ä»·åæ°éï¼åç®å«ç¨åä»· |
| | | if (productForm.value.quantity) { |
| | | productForm.value.taxInclusiveUnitPrice = |
| | | (Number(productForm.value.taxInclusiveTotalPrice) / Number(productForm.value.quantity)).toFixed(2); |
| | | } |
| | | // å·²ç¥å«ç¨æ»ä»·åå«ç¨åä»·ï¼åç®æ°é |
| | | else if (productForm.value.taxInclusiveUnitPrice) { |
| | | productForm.value.quantity = |
| | | (Number(productForm.value.taxInclusiveTotalPrice) / Number(productForm.value.taxInclusiveUnitPrice)).toFixed(2); |
| | | } |
| | | // åç®ä¸å«ç¨æ»ä»· |
| | | productForm.value.taxExclusiveTotalPrice = |
| | | (Number(productForm.value.taxInclusiveTotalPrice) / (1 + taxRate / 100)).toFixed(2); |
| | | } else if (field === 'taxExclusiveTotalPrice') { |
| | | // åç®å«ç¨æ»ä»· |
| | | productForm.value.taxInclusiveTotalPrice = |
| | | (Number(productForm.value.taxExclusiveTotalPrice) * (1 + taxRate / 100)).toFixed(2); |
| | | // å·²ç¥æ°éï¼åç®å«ç¨åä»· |
| | | if (productForm.value.quantity) { |
| | | productForm.value.taxInclusiveUnitPrice = |
| | | (Number(productForm.value.taxInclusiveTotalPrice) / Number(productForm.value.quantity)).toFixed(2); |
| | | } |
| | | // å·²ç¥å«ç¨åä»·ï¼åç®æ°é |
| | | else if (productForm.value.taxInclusiveUnitPrice) { |
| | | productForm.value.quantity = |
| | | (Number(productForm.value.taxInclusiveTotalPrice) / Number(productForm.value.taxInclusiveUnitPrice)).toFixed(2); |
| | | } |
| | | } |
| | | }; |
| | | // éå®ååéæ©æ¹åæ¹æ³ |
| | | const salesLedgerChange = async (row) => { |
| | | const index = salesContractList.value.findIndex((item) => item.id === row); |
| | | if (index > -1) { |
| | | form.value.projectName = salesContractList.value[index].projectName; |
| | | await querygProductInfoByContractNo(); |
| | | } |
| | | }; |
| | | |
| | | const querygProductInfoByContractNo = async () => { |
| | | const { code, data } = await getProductInfoByContractNo({ |
| | | contractNo: form.value.salesLedgerId, |
| | | }); |
| | | if (code == 200) { |
| | | productData.value = data; |
| | | } |
| | | }; |
| | | |
| | | // æ¾ç¤ºäºç»´ç |
| | | const showQRCode = async (row) => { |
| | | try { |
| | | // æå»ºäºç»´ç å
容ï¼åªå
å«éè´ååå·ï¼çº¯ææ¬ï¼ |
| | | const qrContent = row.purchaseContractNumber || ''; |
| | | // æ£æ¥å
容æ¯å¦ä¸ºç©º |
| | | if (!qrContent || qrContent.trim() === '') { |
| | | proxy.$modal.msgWarning("è¯¥è¡æ²¡æéè´ååå·ï¼æ æ³çæäºç»´ç "); |
| | | if (unauthorizedData.length > 0) { |
| | | proxy.$modal.msgWarning("ä¸å¯å é¤ä»äººç»´æ¤çæ°æ®"); |
| | | return; |
| | | } |
| | | ids = selectedRows.value.map(item => item.id); |
| | | } else { |
| | | proxy.$modal.msgWarning("è¯·éæ©æ°æ®"); |
| | | return; |
| | | } |
| | | qrCodeUrl.value = await QRCode.toDataURL(qrContent, { |
| | | width: 200, |
| | | margin: 2, |
| | | color: { |
| | | dark: '#000000', |
| | | light: '#FFFFFF' |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | delPurchase(ids).then(res => { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | getList(); |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | // è·åå½åæ¥æå¹¶æ ¼å¼å为 YYYY-MM-DD |
| | | function getCurrentDate() { |
| | | const today = new Date(); |
| | | const year = today.getFullYear(); |
| | | const month = String(today.getMonth() + 1).padStart(2, "0"); // æä»½ä»0å¼å§ |
| | | const day = String(today.getDate()).padStart(2, "0"); |
| | | return `${year}-${month}-${day}`; |
| | | } |
| | | const mathNum = () => { |
| | | if (!productForm.value.taxRate) { |
| | | proxy.$modal.msgWarning("请å
éæ©ç¨ç"); |
| | | return; |
| | | } |
| | | if (!productForm.value.taxInclusiveUnitPrice) { |
| | | return; |
| | | } |
| | | if (!productForm.value.quantity) { |
| | | return; |
| | | } |
| | | // å«ç¨æ»ä»·è®¡ç® |
| | | productForm.value.taxInclusiveTotalPrice = |
| | | proxy.calculateTaxIncludeTotalPrice( |
| | | productForm.value.taxInclusiveUnitPrice, |
| | | productForm.value.quantity |
| | | ); |
| | | if (productForm.value.taxRate) { |
| | | // ä¸å«ç¨æ»ä»·è®¡ç® |
| | | productForm.value.taxExclusiveTotalPrice = |
| | | proxy.calculateTaxExclusiveTotalPrice( |
| | | productForm.value.taxInclusiveTotalPrice, |
| | | productForm.value.taxRate |
| | | ); |
| | | } |
| | | }; |
| | | const reverseMathNum = field => { |
| | | if (!productForm.value.taxRate) { |
| | | proxy.$modal.msgWarning("请å
éæ©ç¨ç"); |
| | | return; |
| | | } |
| | | const taxRate = Number(productForm.value.taxRate); |
| | | if (!taxRate) return; |
| | | |
| | | // ç¡®ä¿è¾å
¥å¼ä¸ä¸ºè´æ° |
| | | if ( |
| | | field === "taxInclusiveTotalPrice" || |
| | | field === "taxExclusiveTotalPrice" |
| | | ) { |
| | | const value = Number(productForm.value[field]); |
| | | if (value < 0) { |
| | | productForm.value[field] = "0"; |
| | | proxy.$modal.msgWarning("å¼ä¸è½å°äº0"); |
| | | return; |
| | | } |
| | | } |
| | | |
| | | if (field === "taxInclusiveTotalPrice") { |
| | | // å·²ç¥å«ç¨æ»ä»·åæ°éï¼åç®å«ç¨åä»· |
| | | if (productForm.value.quantity) { |
| | | productForm.value.taxInclusiveUnitPrice = ( |
| | | Number(productForm.value.taxInclusiveTotalPrice) / |
| | | Number(productForm.value.quantity) |
| | | ).toFixed(2); |
| | | // ç¡®ä¿ç»æä¸ä¸ºè´æ° |
| | | if (Number(productForm.value.taxInclusiveUnitPrice) < 0) { |
| | | productForm.value.taxInclusiveUnitPrice = "0"; |
| | | } |
| | | } |
| | | // å·²ç¥å«ç¨æ»ä»·åå«ç¨åä»·ï¼åç®æ°é |
| | | else if (productForm.value.taxInclusiveUnitPrice) { |
| | | productForm.value.quantity = ( |
| | | Number(productForm.value.taxInclusiveTotalPrice) / |
| | | Number(productForm.value.taxInclusiveUnitPrice) |
| | | ).toFixed(2); |
| | | // ç¡®ä¿ç»æä¸ä¸ºè´æ° |
| | | if (Number(productForm.value.quantity) < 0) { |
| | | productForm.value.quantity = "0"; |
| | | } |
| | | } |
| | | // åç®ä¸å«ç¨æ»ä»· |
| | | productForm.value.taxExclusiveTotalPrice = ( |
| | | Number(productForm.value.taxInclusiveTotalPrice) / |
| | | (1 + taxRate / 100) |
| | | ).toFixed(2); |
| | | // ç¡®ä¿ç»æä¸ä¸ºè´æ° |
| | | if (Number(productForm.value.taxExclusiveTotalPrice) < 0) { |
| | | productForm.value.taxExclusiveTotalPrice = "0"; |
| | | } |
| | | } else if (field === "taxExclusiveTotalPrice") { |
| | | // åç®å«ç¨æ»ä»· |
| | | productForm.value.taxInclusiveTotalPrice = ( |
| | | Number(productForm.value.taxExclusiveTotalPrice) * |
| | | (1 + taxRate / 100) |
| | | ).toFixed(2); |
| | | // ç¡®ä¿ç»æä¸ä¸ºè´æ° |
| | | if (Number(productForm.value.taxInclusiveTotalPrice) < 0) { |
| | | productForm.value.taxInclusiveTotalPrice = "0"; |
| | | } |
| | | // å·²ç¥æ°éï¼åç®å«ç¨åä»· |
| | | if (productForm.value.quantity) { |
| | | productForm.value.taxInclusiveUnitPrice = ( |
| | | Number(productForm.value.taxInclusiveTotalPrice) / |
| | | Number(productForm.value.quantity) |
| | | ).toFixed(2); |
| | | // ç¡®ä¿ç»æä¸ä¸ºè´æ° |
| | | if (Number(productForm.value.taxInclusiveUnitPrice) < 0) { |
| | | productForm.value.taxInclusiveUnitPrice = "0"; |
| | | } |
| | | } |
| | | // å·²ç¥å«ç¨åä»·ï¼åç®æ°é |
| | | else if (productForm.value.taxInclusiveUnitPrice) { |
| | | productForm.value.quantity = ( |
| | | Number(productForm.value.taxInclusiveTotalPrice) / |
| | | Number(productForm.value.taxInclusiveUnitPrice) |
| | | ).toFixed(2); |
| | | // ç¡®ä¿ç»æä¸ä¸ºè´æ° |
| | | if (Number(productForm.value.quantity) < 0) { |
| | | productForm.value.quantity = "0"; |
| | | } |
| | | } |
| | | } |
| | | }; |
| | | // éå®ååéæ©æ¹åæ¹æ³ |
| | | const salesLedgerChange = async row => { |
| | | console.log("row", row); |
| | | var index = salesContractList.value.findIndex(item => item.id == row); |
| | | console.log("index", index); |
| | | if (index > -1) { |
| | | await querygProductInfoByContractNo(); |
| | | } |
| | | }; |
| | | |
| | | const querygProductInfoByContractNo = async () => { |
| | | const { code, data } = await getProductInfoByContractNo({ |
| | | contractNo: form.value.salesLedgerId, |
| | | }); |
| | | qrCodeDialogVisible.value = true; |
| | | } catch (error) { |
| | | console.error('çæäºç»´ç 失败:', error); |
| | | proxy.$modal.msgError("çæäºç»´ç 失败ï¼" + error.message); |
| | | } |
| | | }; |
| | | if (code == 200) { |
| | | productData.value = data; |
| | | } |
| | | }; |
| | | |
| | | // ä¸è½½äºç»´ç |
| | | const downloadQRCode = () => { |
| | | if (!qrCodeUrl.value) { |
| | | proxy.$modal.msgWarning("äºç»´ç æªçæ"); |
| | | return; |
| | | } |
| | | const fileListRef = ref(null); |
| | | const downLoadFile = row => { |
| | | fileListRef.value.open(row.salesLedgerFiles); |
| | | }; |
| | | |
| | | try { |
| | | const a = document.createElement('a'); |
| | | // æ¾ç¤ºäºç»´ç |
| | | const showQRCode = async row => { |
| | | try { |
| | | // æå»ºäºç»´ç å
容ï¼åªå
å«éè´ååå·ï¼çº¯ææ¬ï¼ |
| | | const qrContent = row.purchaseContractNumber || ""; |
| | | // æ£æ¥å
容æ¯å¦ä¸ºç©º |
| | | if (!qrContent || qrContent.trim() === "") { |
| | | proxy.$modal.msgWarning("è¯¥è¡æ²¡æéè´ååå·ï¼æ æ³çæäºç»´ç "); |
| | | return; |
| | | } |
| | | qrCodeUrl.value = await QRCode.toDataURL(qrContent, { |
| | | width: 200, |
| | | margin: 2, |
| | | color: { |
| | | dark: "#000000", |
| | | light: "#FFFFFF", |
| | | }, |
| | | }); |
| | | qrCodeDialogVisible.value = true; |
| | | } catch (error) { |
| | | console.error("çæäºç»´ç 失败:", error); |
| | | proxy.$modal.msgError("çæäºç»´ç 失败ï¼" + error.message); |
| | | } |
| | | }; |
| | | |
| | | // ä¸è½½äºç»´ç |
| | | const downloadQRCode = () => { |
| | | if (!qrCodeUrl.value) { |
| | | proxy.$modal.msgWarning("äºç»´ç æªçæ"); |
| | | return; |
| | | } |
| | | |
| | | const a = document.createElement("a"); |
| | | a.href = qrCodeUrl.value; |
| | | a.download = `éè´ååå·äºç»´ç _${dayjs().format('YYYYMMDDHHmmss')}.png`; |
| | | a.download = `éè´ååå·äºç»´ç _${new Date().getTime()}.png`; |
| | | document.body.appendChild(a); |
| | | a.click(); |
| | | document.body.removeChild(a); |
| | | proxy.$modal.msgSuccess("ä¸è½½æå"); |
| | | } catch (error) { |
| | | console.error('ä¸è½½äºç»´ç 失败:', error); |
| | | proxy.$modal.msgError("ä¸è½½å¤±è´¥ï¼è¯·ç¨åéè¯"); |
| | | } |
| | | }; |
| | | }; |
| | | |
| | | // æ«ç æ°å¢å¯¹è¯æ¡ç¸å
³åé |
| | | const scanAddDialogVisible = ref(false); |
| | | const scanAddForm = reactive({ |
| | | scanContent: "", |
| | | purchaseContractNumber: "", |
| | | supplierName: "", |
| | | projectName: "", |
| | | contractAmount: "", |
| | | paymentMethod: "", |
| | | recorderName: "", |
| | | scanRemark: "", |
| | | }); |
| | | const scanAddRules = { |
| | | purchaseContractNumber: [{ required: true, message: "请è¾å
¥éè´ååå·", trigger: "blur" }], |
| | | supplierName: [{ required: true, message: "请è¾å
¥ä¾åºååç§°", trigger: "blur" }], |
| | | projectName: [{ required: true, message: "请è¾å
¥é¡¹ç®åç§°", trigger: "blur" }], |
| | | }; |
| | | // æ«ç æ°å¢å¯¹è¯æ¡ç¸å
³åé |
| | | const scanAddDialogVisible = ref(false); |
| | | const scanAddForm = reactive({ |
| | | scanContent: "", |
| | | purchaseContractNumber: "", |
| | | supplierName: "", |
| | | projectName: "", |
| | | contractAmount: "", |
| | | paymentMethod: "", |
| | | recorderName: "", |
| | | scanRemark: "", |
| | | }); |
| | | const scanAddRules = { |
| | | purchaseContractNumber: [ |
| | | { required: true, message: "请è¾å
¥éè´ååå·", trigger: "blur" }, |
| | | ], |
| | | supplierName: [ |
| | | { required: true, message: "请è¾å
¥ä¾åºååç§°", trigger: "blur" }, |
| | | ], |
| | | projectName: [{ required: true, message: "请è¾å
¥é¡¹ç®åç§°", trigger: "blur" }], |
| | | }; |
| | | |
| | | // æ«ç ç»è®°å¯¹è¯æ¡ç¸å
³åé |
| | | const scanDialogVisible = ref(false); |
| | | const scanForm = reactive({ |
| | | purchaseContractNumber: "", |
| | | supplierName: "", |
| | | projectName: "", |
| | | scanTime: "", |
| | | scannerName: "", |
| | | scanStatus: "æªæ«ç ", |
| | | scanRemark: "", |
| | | }); |
| | | const scanRules = { |
| | | scanRemark: [{ required: true, message: "请è¾å
¥æ«ç 夿³¨", trigger: "blur" }], |
| | | }; |
| | | const scanRecords = ref([]); |
| | | // æ«ç ç»è®°å¯¹è¯æ¡ç¸å
³åé |
| | | const scanDialogVisible = ref(false); |
| | | const scanForm = reactive({ |
| | | purchaseContractNumber: "", |
| | | supplierName: "", |
| | | projectName: "", |
| | | scanTime: "", |
| | | scannerName: "", |
| | | scanStatus: "æªæ«ç ", |
| | | scanRemark: "", |
| | | }); |
| | | const scanRules = { |
| | | scanRemark: [{ required: true, message: "请è¾å
¥æ«ç 夿³¨", trigger: "blur" }], |
| | | }; |
| | | const scanRecords = ref([]); |
| | | |
| | | // æå¼æ«ç æ°å¢å¯¹è¯æ¡ |
| | | const openScanAddDialog = () => { |
| | | scanAddForm.scanContent = ""; |
| | | scanAddForm.purchaseContractNumber = ""; |
| | | scanAddForm.supplierName = ""; |
| | | scanAddForm.projectName = ""; |
| | | scanAddForm.contractAmount = ""; |
| | | scanAddForm.paymentMethod = ""; |
| | | scanAddForm.recorderName = userStore.nickName; |
| | | scanAddForm.scanRemark = ""; |
| | | scanAddDialogVisible.value = true; |
| | | }; |
| | | // æå¼æ«ç æ°å¢å¯¹è¯æ¡ |
| | | const openScanAddDialog = () => { |
| | | scanAddForm.scanContent = ""; |
| | | scanAddForm.purchaseContractNumber = ""; |
| | | scanAddForm.supplierName = ""; |
| | | scanAddForm.projectName = ""; |
| | | scanAddForm.contractAmount = ""; |
| | | scanAddForm.paymentMethod = ""; |
| | | scanAddForm.recorderName = userStore.nickName; |
| | | scanAddForm.scanRemark = ""; |
| | | scanAddDialogVisible.value = true; |
| | | }; |
| | | |
| | | // è§£ææ«ç å
å®¹ï¼æ¨¡æè§£æäºç»´ç æ°æ®ï¼ |
| | | const parseScanContent = (content) => { |
| | | if (!content) return; |
| | | // è§£ææ«ç å
å®¹ï¼æ¨¡æè§£æäºç»´ç æ°æ®ï¼ |
| | | const parseScanContent = content => { |
| | | if (!content) return; |
| | | |
| | | // 模æè§£æäºç»´ç å
容ï¼è¿éå¯ä»¥æ ¹æ®å®é
éæ±è°æ´è§£æé»è¾ |
| | | // å设æ«ç å
å®¹æ ¼å¼ä¸ºï¼ååå·|ä¾åºå|项ç®|éé¢|仿¬¾æ¹å¼ |
| | | const parts = content.split('|'); |
| | | if (parts.length >= 3) { |
| | | scanAddForm.purchaseContractNumber = parts[0] || ""; |
| | | scanAddForm.supplierName = parts[1] || ""; |
| | | scanAddForm.projectName = parts[2] || ""; |
| | | scanAddForm.contractAmount = parts[3] || ""; |
| | | scanAddForm.paymentMethod = parts[4] || ""; |
| | | } |
| | | }; |
| | | |
| | | // å
³éæ«ç æ°å¢å¯¹è¯æ¡ |
| | | const closeScanAddDialog = () => { |
| | | scanAddDialogVisible.value = false; |
| | | proxy.resetForm("scanAddFormRef"); |
| | | }; |
| | | |
| | | // æäº¤æ«ç æ°å¢ |
| | | const submitScanAdd = async () => { |
| | | try { |
| | | const valid = await proxy.$refs["scanAddFormRef"].validate().catch(() => false); |
| | | if (!valid) { |
| | | return; |
| | | // 模æè§£æäºç»´ç å
容ï¼è¿éå¯ä»¥æ ¹æ®å®é
éæ±è°æ´è§£æé»è¾ |
| | | // å设æ«ç å
å®¹æ ¼å¼ä¸ºï¼ååå·|ä¾åºå|éé¢|仿¬¾æ¹å¼ |
| | | const parts = content.split("|"); |
| | | if (parts.length >= 2) { |
| | | scanAddForm.purchaseContractNumber = parts[0] || ""; |
| | | scanAddForm.supplierName = parts[1] || ""; |
| | | scanAddForm.contractAmount = parts[2] || ""; |
| | | scanAddForm.paymentMethod = parts[3] || ""; |
| | | scanAddForm.projectName = parts[4] || ""; |
| | | // scanAddForm.contractAmount = parts[3] || ""; |
| | | // scanAddForm.paymentMethod = parts[4] || ""; |
| | | } |
| | | |
| | | // æå»ºæ°å¢æ°æ® |
| | | const newData = { |
| | | purchaseContractNumber: scanAddForm.purchaseContractNumber, |
| | | supplierName: scanAddForm.supplierName, |
| | | projectName: scanAddForm.projectName, |
| | | contractAmount: scanAddForm.contractAmount, |
| | | paymentMethod: scanAddForm.paymentMethod, |
| | | recorderName: scanAddForm.recorderName, |
| | | entryDate: getCurrentDate(), |
| | | remark: scanAddForm.scanRemark, |
| | | type: 2 |
| | | }; |
| | | }; |
| | | |
| | | // await addOrEditPurchase(newData); |
| | | |
| | | proxy.$modal.msgSuccess("æ«ç æ°å¢æåï¼"); |
| | | closeScanAddDialog(); |
| | | getList(); // å·æ°å表 |
| | | } catch (error) { |
| | | console.error('æäº¤æ«ç æ°å¢å¤±è´¥:', error); |
| | | proxy.$modal.msgError("æäº¤å¤±è´¥ï¼è¯·ç¨åéè¯"); |
| | | } |
| | | }; |
| | | // å
³éæ«ç æ°å¢å¯¹è¯æ¡ |
| | | const closeScanAddDialog = () => { |
| | | scanAddDialogVisible.value = false; |
| | | proxy.resetForm("scanAddFormRef"); |
| | | }; |
| | | |
| | | // æå¼æ«ç ç»è®°å¯¹è¯æ¡ |
| | | const openScanDialog = (row) => { |
| | | scanForm.purchaseContractNumber = row.purchaseContractNumber; |
| | | scanForm.supplierName = row.supplierName; |
| | | scanForm.projectName = row.projectName; |
| | | scanForm.scanTime = getCurrentDateTime(); |
| | | scanForm.scannerName = userStore.nickName; |
| | | scanForm.scanStatus = "æªæ«ç "; |
| | | scanForm.scanRemark = ""; |
| | | scanRecords.value = []; |
| | | scanDialogVisible.value = true; |
| | | }; |
| | | // æäº¤æ«ç æ°å¢ |
| | | const submitScanAdd = () => { |
| | | proxy.$refs["scanAddFormRef"].validate(valid => { |
| | | if (valid) { |
| | | // æå»ºæ°å¢æ°æ® |
| | | const newData = { |
| | | purchaseContractNumber: scanAddForm.purchaseContractNumber, |
| | | supplierName: scanAddForm.supplierName, |
| | | projectName: scanAddForm.projectName, |
| | | contractAmount: scanAddForm.contractAmount, |
| | | paymentMethod: scanAddForm.paymentMethod, |
| | | recorderName: scanAddForm.recorderName, |
| | | entryDate: getCurrentDate(), |
| | | remark: scanAddForm.scanRemark, |
| | | type: 2, |
| | | }; |
| | | |
| | | // å
³éæ«ç ç»è®°å¯¹è¯æ¡ |
| | | const closeScanDialog = () => { |
| | | scanDialogVisible.value = false; |
| | | proxy.resetForm("scanFormRef"); |
| | | }; |
| | | // æ¨¡ææ°å¢æå |
| | | proxy.$modal.msgSuccess("æ«ç æ°å¢æåï¼"); |
| | | closeScanAddDialog(); |
| | | |
| | | // æäº¤æ«ç ç»è®° |
| | | const submitScan = async () => { |
| | | try { |
| | | const valid = await proxy.$refs["scanFormRef"].validate().catch(() => false); |
| | | if (!valid) { |
| | | return; |
| | | } |
| | | |
| | | // æ·»å æ«ç è®°å½ |
| | | scanRecords.value.push({ |
| | | ...scanForm, |
| | | id: Date.now(), // 模æID |
| | | scanTime: getCurrentDateTime(), |
| | | // å¯ä»¥éæ©æ¯å¦å·æ°å表 |
| | | // getList(); |
| | | } |
| | | }); |
| | | scanForm.scanStatus = "å·²æ«ç "; |
| | | scanForm.scanRemark = scanForm.scanRemark || "æ "; |
| | | proxy.$modal.msgSuccess("æ«ç ç»è®°æåï¼"); |
| | | closeScanDialog(); |
| | | } catch (error) { |
| | | console.error('æäº¤æ«ç ç»è®°å¤±è´¥:', error); |
| | | proxy.$modal.msgError("æäº¤å¤±è´¥ï¼è¯·ç¨åéè¯"); |
| | | }; |
| | | |
| | | // æå¼æ«ç ç»è®°å¯¹è¯æ¡ |
| | | const openScanDialog = row => { |
| | | scanForm.purchaseContractNumber = row.purchaseContractNumber; |
| | | scanForm.supplierName = row.supplierName; |
| | | scanForm.projectName = row.projectName; |
| | | scanForm.scanTime = getCurrentDateTime(); |
| | | scanForm.scannerName = userStore.nickName; |
| | | scanForm.scanStatus = "æªæ«ç "; |
| | | scanForm.scanRemark = ""; |
| | | scanRecords.value = []; |
| | | scanDialogVisible.value = true; |
| | | }; |
| | | |
| | | // å
³éæ«ç ç»è®°å¯¹è¯æ¡ |
| | | const closeScanDialog = () => { |
| | | scanDialogVisible.value = false; |
| | | proxy.resetForm("scanFormRef"); |
| | | }; |
| | | |
| | | // æäº¤æ«ç ç»è®° |
| | | const submitScan = () => { |
| | | proxy.$refs["scanFormRef"].validate(valid => { |
| | | if (valid) { |
| | | // æ·»å æ«ç è®°å½ |
| | | scanRecords.value.push({ |
| | | ...scanForm, |
| | | id: Date.now(), // 模æID |
| | | scanTime: getCurrentDateTime(), |
| | | }); |
| | | scanForm.scanStatus = "å·²æ«ç "; |
| | | scanForm.scanRemark = scanForm.scanRemark || "æ "; |
| | | proxy.$modal.msgSuccess("æ«ç ç»è®°æåï¼"); |
| | | closeScanDialog(); |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | // è·åå½åæ¥ææ¶é´ |
| | | function getCurrentDateTime() { |
| | | const now = new Date(); |
| | | const year = now.getFullYear(); |
| | | const month = String(now.getMonth() + 1).padStart(2, "0"); |
| | | const day = String(now.getDate()).padStart(2, "0"); |
| | | const hours = String(now.getHours()).padStart(2, "0"); |
| | | const minutes = String(now.getMinutes()).padStart(2, "0"); |
| | | const seconds = String(now.getSeconds()).padStart(2, "0"); |
| | | return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; |
| | | } |
| | | }; |
| | | |
| | | // è·åå½åæ¥ææ¶é´ |
| | | function getCurrentDateTime() { |
| | | return dayjs().format("YYYY-MM-DD HH:mm:ss"); |
| | | } |
| | | // æ·»å è¡ç±»åæ¹æ³ |
| | | const tableRowClassName = ({ row }) => { |
| | | return row.isInvalid ? "invalid-row" : ""; |
| | | }; |
| | | |
| | | // æ·»å è¡ç±»åæ¹æ³ |
| | | const tableRowClassName = ({ row }) => { |
| | | return row.isInvalid ? 'invalid-row' : ''; |
| | | }; |
| | | // è·å模æ¿ä¿¡æ¯ |
| | | const getTemplateList = async () => { |
| | | let res = await getPurchaseTemplateList(); |
| | | if (res && res.code === 200 && Array.isArray(res.data)) { |
| | | templateList.value = res.data; |
| | | } |
| | | }; |
| | | |
| | | // è·å模æ¿ä¿¡æ¯ |
| | | const getTemplateList =async ()=>{ |
| | | let res = await getPurchaseTemplateList() |
| | | if(res && res.code===200 && Array.isArray(res.data)){ |
| | | templateList.value = res.data |
| | | } |
| | | } |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | getTemplateList(); |
| | | |
| | | }); |
| | | onMounted(() => { |
| | | getList(); |
| | | getTemplateList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .invalid-row { |
| | | opacity: 0.6; |
| | | background-color: #f5f7fa; |
| | | } |
| | | .el-row{ |
| | | justify-content: space-between; |
| | | align-items: center |
| | | } |
| | | .no-arrow-select { |
| | | --el-select-suffix-icon-color: transparent; /* éèé»è®¤ä¸æç®å¤´ */ |
| | | } |
| | | .select-button-group { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .invalid-row { |
| | | opacity: 0.6; |
| | | background-color: #f5f7fa; |
| | | } |
| | | .el-row { |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | } |
| | | .no-arrow-select { |
| | | --el-select-suffix-icon-color: transparent; /* éèé»è®¤ä¸æç®å¤´ */ |
| | | } |
| | | .select-button-group { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | </style> |
| | |
| | | </el-card> |
| | | |
| | | <!-- æ°å¢/ç¼è¾å¯¹è¯æ¡ --> |
| | | <el-dialog |
| | | <FormDialog |
| | | v-model="dialogVisible" |
| | | :title="dialogType === 'add' ? 'æ°å¢éè´è®¡å' : 'ç¼è¾éè´è®¡å'" |
| | | width="1000px" |
| | | :width="'1000px'" |
| | | :operation-type="dialogType" |
| | | :close-on-click-modal="false" |
| | | @close="dialogVisible = false" |
| | | @confirm="handleSubmit" |
| | | @cancel="dialogVisible = false" |
| | | > |
| | | <div class="form-container"> |
| | | <!-- åºæ¬ä¿¡æ¯ --> |
| | |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button @click="dialogVisible = false">åæ¶</el-button> |
| | | <el-button type="primary" @click="handleSubmit" :loading="submitLoading">ç¡®å®</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | </FormDialog> |
| | | |
| | | <!-- 产åéæ©å¯¹è¯æ¡ --> |
| | | <el-dialog |
| | | <FormDialog |
| | | v-model="productSelectDialogVisible" |
| | | title="éæ©äº§å" |
| | | width="800px" |
| | | :width="'800px'" |
| | | :close-on-click-modal="false" |
| | | @close="productSelectDialogVisible = false" |
| | | @confirm="handleConfirmProductSelection" |
| | | @cancel="productSelectDialogVisible = false" |
| | | > |
| | | <div class="product-select"> |
| | | <el-alert |
| | |
| | | <el-table-column prop="inboundNum0" label="é¢è®¡å
¥åº" width="100" align="right" /> |
| | | </el-table> |
| | | </div> |
| | | |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button @click="productSelectDialogVisible = false">åæ¶</el-button> |
| | | <el-button type="primary" @click="handleConfirmProductSelection" :disabled="selectedProducts.length === 0"> |
| | | ç¡®è®¤è®¡ç® |
| | | </el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | </FormDialog> |
| | | |
| | | <!-- 计ç®ç»æå¯¹è¯æ¡ --> |
| | | <el-dialog |
| | | <FormDialog |
| | | v-model="calculateDialogVisible" |
| | | title="éè´è®¡ç®ç»æ" |
| | | width="1000px" |
| | | :width="'1000px'" |
| | | :close-on-click-modal="false" |
| | | @close="calculateDialogVisible = false" |
| | | @confirm="handleCreatePurchaseOrder" |
| | | @cancel="calculateDialogVisible = false" |
| | | > |
| | | <div class="calculate-result"> |
| | | <el-alert |
| | |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button @click="calculateDialogVisible = false">å
³é</el-button> |
| | | <el-button type="primary" @click="handleCreatePurchaseOrder">确认</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | </FormDialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import FormDialog from '@/components/Dialog/FormDialog.vue'; |
| | | import {ref, reactive, onMounted, getCurrentInstance} from 'vue' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | import { Search, Refresh, Plus, Download } from '@element-plus/icons-vue' |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <!-- æ¥è¡¨éæ©å¨ --> |
| | | <el-card class="report-selector" shadow="never"> |
| | | <el-tabs v-model="activeReport" @tab-change="handleReportChange"> |
| | | <el-tab-pane label="éè´è®¢åæ§è¡æ±æ»è¡¨" name="orderSummary"> |
| | | <template #label> |
| | | <span class="tab-label"> |
| | | <el-icon><Document /></el-icon> |
| | | éè´è®¢åæ§è¡æ±æ»è¡¨ |
| | | </span> |
| | | </template> |
| | | </el-tab-pane> |
| | | <el-tab-pane label="éè´è®¢åæ§è¡æç»è¡¨" name="orderDetail"> |
| | | <template #label> |
| | | <span class="tab-label"> |
| | | <el-icon><List /></el-icon> |
| | | éè´è®¢åæ§è¡æç»è¡¨ |
| | | </span> |
| | | </template> |
| | | </el-tab-pane> |
| | | <el-tab-pane label="éè´ä¸å¡æ±æ»è¡¨" name="businessSummary"> |
| | | <template #label> |
| | | <span class="tab-label"> |
| | | <el-icon><TrendCharts /></el-icon> |
| | | éè´ä¸å¡æ±æ»è¡¨ |
| | | </span> |
| | | </template> |
| | | </el-tab-pane> |
| | | <el-tab-pane label="ä¾åºåä¾è´§æ±æ»è¡¨" name="supplierSummary"> |
| | | <template #label> |
| | | <span class="tab-label"> |
| | | <el-icon><Shop /></el-icon> |
| | | ä¾åºåä¾è´§æ±æ»è¡¨ |
| | | </span> |
| | | </template> |
| | | </el-tab-pane> |
| | | </el-tabs> |
| | | </el-card> |
| | | |
| | | <!-- æ¥è¯¢æ¡ä»¶ --> |
| | | <el-card class="search-card" shadow="never"> |
| | | <el-form :model="searchForm" :inline="true" class="search-form"> |
| | | <el-form :model="searchForm" :inline="true" class="search-form"> |
| | | <el-form-item label="æ¶é´èå´ï¼"> |
| | | <el-date-picker |
| | | v-model="searchForm.dateRange" |
| | |
| | | style="width: 240px" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="ä¾åºåï¼" v-if="activeReport === 'supplierSummary'"> |
| | | <el-select v-model="searchForm.supplierId" placeholder="è¯·éæ©ä¾åºå" clearable style="width: 200px"> |
| | | <el-option |
| | | v-for="supplier in supplierList" |
| | | :key="supplier.id" |
| | | :label="supplier.name" |
| | | :value="supplier.id" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="ååç±»å«ï¼" v-if="activeReport === 'businessSummary'"> |
| | | <el-select v-model="searchForm.categoryId" placeholder="è¯·éæ©ååç±»å«" clearable style="width: 200px"> |
| | | <el-option |
| | | v-for="category in categoryList" |
| | | :key="category.id" |
| | | :label="category.name" |
| | | :value="category.id" |
| | | /> |
| | | </el-select> |
| | | <el-form-item label="产å大类ï¼"> |
| | | <el-tree-select |
| | | v-model="searchForm.productCategory" |
| | | placeholder="è¯·éæ©ååç±»å«" |
| | | clearable |
| | | check-strictly |
| | | :data="productOptions" |
| | | :render-after-expand="false" |
| | | style="width: 200px" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="handleSearch" :loading="loading"> |
| | | <el-icon><Search /></el-icon> |
| | | æ¥è¯¢ |
| | | </el-button> |
| | | <el-button @click="resetSearch"> |
| | | <el-icon><Refresh /></el-icon> |
| | | éç½® |
| | | </el-button> |
| | | <el-button type="success" @click="exportReport"> |
| | | <el-button type="info" @click="exportReport"> |
| | | <el-icon><Download /></el-icon> |
| | | å¯¼åº |
| | | </el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </el-card> |
| | | |
| | | <!-- æ¥è¡¨å
容 --> |
| | | <el-card class="report-content" shadow="never"> |
| | | <!-- éè´è®¢åæ§è¡æ±æ»è¡¨ --> |
| | | <div v-if="activeReport === 'orderSummary'" class="report-section"> |
| | | <div class="section-header"> |
| | | <h3>éè´è®¢åæ§è¡æ±æ»è¡¨</h3> |
| | | <div class="summary-stats"> |
| | | <div class="stat-item"> |
| | | <span class="stat-label">æ»è®¢åæ°ï¼</span> |
| | | <span class="stat-value">{{ orderSummaryStats.totalOrders }}</span> |
| | | </div> |
| | | <div class="stat-item"> |
| | | <span class="stat-label">æ»éé¢ï¼</span> |
| | | <span class="stat-value">Â¥{{ orderSummaryStats.totalAmount.toLocaleString() }}</span> |
| | | </div> |
| | | <div class="stat-item"> |
| | | <span class="stat-label">宿çï¼</span> |
| | | <span class="stat-value">{{ orderSummaryStats.completionRate }}%</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <el-table :data="orderSummaryData" border v-loading="loading" stripe style="width: 100%"> |
| | | <el-table-column label="订åç¼å·" prop="orderNo" width="180" fixed="left" /> |
| | | <el-table-column label="ä¾åºååç§°" prop="supplierName" min-width="150" /> |
| | | <el-table-column label="è®¢åæ¥æ" prop="orderDate" width="120" /> |
| | | <el-table-column label="计å交æ" prop="plannedDelivery" width="120" /> |
| | | <el-table-column label="å®é
交æ" prop="actualDelivery" width="120" /> |
| | | <el-table-column label="订åéé¢" prop="orderAmount" width="120"> |
| | | <template #default="{ row }">Â¥{{ row.orderAmount.toLocaleString() }}</template> |
| | | </el-table-column> |
| | | <el-table-column label="å·²ä»éé¢" prop="paidAmount" width="120"> |
| | | <template #default="{ row }">Â¥{{ row.paidAmount.toLocaleString() }}</template> |
| | | </el-table-column> |
| | | <el-table-column label="å®æç¶æ" prop="status" width="100"> |
| | | <template #default="{ row }"> |
| | | <el-tag :type="getStatusType(row.status)">{{ getStatusText(row.status) }}</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="宿ç" prop="completionRate" width="100"> |
| | | <template #default="{ row }">{{ row.completionRate }}%</template> |
| | | </el-table-column> |
| | | <el-table-column label="å»¶è¿å¤©æ°" prop="delayDays" width="100"> |
| | | <template #default="{ row }"> |
| | | <span :class="{ 'delay-text': row.delayDays > 0 }">{{ row.delayDays }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | |
| | | <!-- éè´è®¢åæ§è¡æç»è¡¨ --> |
| | | <div v-if="activeReport === 'orderDetail'" class="report-section"> |
| | | <div class="section-header"> |
| | | <h3>éè´è®¢åæ§è¡æç»è¡¨</h3> |
| | | <div class="summary-stats"> |
| | | <div class="stat-item"> |
| | | <span class="stat-label">æç»æ¡æ°ï¼</span> |
| | | <span class="stat-value">{{ orderDetailStats.totalItems }}</span> |
| | | </div> |
| | | <div class="stat-item"> |
| | | <span class="stat-label">å·²æ¶è´§ï¼</span> |
| | | <span class="stat-value">{{ orderDetailStats.receivedItems }}</span> |
| | | </div> |
| | | <div class="stat-item"> |
| | | <span class="stat-label">å¾
æ¶è´§ï¼</span> |
| | | <span class="stat-value">{{ orderDetailStats.pendingItems }}</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <el-table :data="orderDetailData" border v-loading="loading" stripe style="width: 100%"> |
| | | <el-table-column label="订åç¼å·" prop="orderNo" width="150" fixed="left" /> |
| | | <el-table-column label="ååç¼ç " prop="productCode" width="120" /> |
| | | <el-table-column label="åååç§°" prop="productName" min-width="200" /> |
| | | <el-table-column label="è§æ ¼åå·" prop="specification" min-width="150" /> |
| | | <el-table-column label="åä½" prop="unit" width="80" /> |
| | | <el-table-column label="è®¡åæ°é" prop="plannedQuantity" width="100" /> |
| | | <el-table-column label="å·²æ¶è´§æ°é" prop="receivedQuantity" width="120" /> |
| | | <el-table-column label="å¾
æ¶è´§æ°é" prop="pendingQuantity" width="120" /> |
| | | <el-table-column label="åä»·" prop="unitPrice" width="100"> |
| | | <template #default="{ row }">Â¥{{ row.unitPrice.toFixed(2) }}</template> |
| | | </el-table-column> |
| | | <el-table-column label="å°è®¡" prop="subtotal" width="120"> |
| | | <template #default="{ row }">Â¥{{ row.subtotal.toLocaleString() }}</template> |
| | | </el-table-column> |
| | | <el-table-column label="æ¶è´§ç¶æ" prop="status" width="100"> |
| | | <template #default="{ row }"> |
| | | <el-tag :type="getReceiptStatusType(row.status)">{{ getReceiptStatusText(row.status) }}</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="æåæ¶è´§æ¥æ" prop="lastReceiptDate" width="120" /> |
| | | </el-table> |
| | | </div> |
| | | |
| | | <!-- éè´ä¸å¡æ±æ»è¡¨ --> |
| | | <div v-if="activeReport === 'businessSummary'" class="report-section"> |
| | | <div class="report-section"> |
| | | <div class="section-header"> |
| | | <h3>éè´ä¸å¡æ±æ»è¡¨</h3> |
| | | <div class="summary-stats"> |
| | |
| | | <span class="stat-label">ååç§ç±»ï¼</span> |
| | | <span class="stat-value">{{ businessSummaryStats.productTypes }}</span> |
| | | </div> |
| | | <div class="stat-item"> |
| | | <span class="stat-label">ä¾åºåæ°ï¼</span> |
| | | <span class="stat-value">{{ businessSummaryStats.supplierCount }}</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <el-table :data="businessSummaryData" border v-loading="loading" stripe style="width: 100%"> |
| | | <el-table-column label="ååç±»å«" prop="category" width="150" fixed="left" /> |
| | | <el-table-column label="ååç¼ç " prop="productCode" width="120" /> |
| | | <el-table-column label="åååç§°" prop="productName" min-width="200" /> |
| | | <el-table-column label="è§æ ¼åå·" prop="specification" min-width="150" /> |
| | | <el-table-column label="éè´æ°é" prop="purchaseQuantity" width="120" /> |
| | | <el-table-column label="éè´éé¢" prop="purchaseAmount" width="120"> |
| | | <template #default="{ row }">Â¥{{ row.purchaseAmount.toLocaleString() }}</template> |
| | | </el-table-column> |
| | | <el-table-column label="å¹³ååä»·" prop="avgPrice" width="100"> |
| | | <template #default="{ row }">Â¥{{ row.avgPrice.toFixed(2) }}</template> |
| | | </el-table-column> |
| | | <el-table-column label="éè´æ¬¡æ°" prop="purchaseCount" width="100" /> |
| | | <el-table-column label="主è¦ä¾åºå" prop="mainSupplier" min-width="150" /> |
| | | <el-table-column label="æåéè´æ¥æ" prop="lastPurchaseDate" width="120" /> |
| | | </el-table> |
| | | </div> |
| | | |
| | | <!-- ä¾åºåä¾è´§æ±æ»è¡¨ --> |
| | | <div v-if="activeReport === 'supplierSummary'" class="report-section"> |
| | | <div class="section-header"> |
| | | <h3>ä¾åºåä¾è´§æ±æ»è¡¨</h3> |
| | | <div class="summary-stats"> |
| | | <div class="stat-item"> |
| | | <span class="stat-label">ä¾åºåæ»æ°ï¼</span> |
| | | <span class="stat-value">{{ supplierSummaryStats.totalSuppliers }}</span> |
| | | </div> |
| | | <div class="stat-item"> |
| | | <span class="stat-label">ä¾è´§æ»é¢ï¼</span> |
| | | <span class="stat-value">Â¥{{ supplierSummaryStats.totalAmount.toLocaleString() }}</span> |
| | | </div> |
| | | <div class="stat-item"> |
| | | <span class="stat-label">å¹³åè¯åï¼</span> |
| | | <span class="stat-value">{{ supplierSummaryStats.avgRating.toFixed(1) }}</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <el-table :data="supplierSummaryData" border v-loading="loading" stripe style="width: 100%"> |
| | | <el-table-column label="ä¾åºåç¼ç " prop="supplierCode" width="120" fixed="left" /> |
| | | <el-table-column label="ä¾åºååç§°" prop="supplierName" min-width="200" /> |
| | | <el-table-column label="è系人" prop="contactPerson" width="120" /> |
| | | <el-table-column label="èç³»çµè¯" prop="phone" width="130" /> |
| | | <el-table-column label="ä¾è´§è®¢åæ°" prop="orderCount" width="120" /> |
| | | <el-table-column label="ä¾è´§éé¢" prop="supplyAmount" width="120"> |
| | | <template #default="{ row }">Â¥{{ row.supplyAmount.toLocaleString() }}</template> |
| | | </el-table-column> |
| | | <el-table-column label="å·²ä»éé¢" prop="paidAmount" width="120"> |
| | | <template #default="{ row }">Â¥{{ row.paidAmount.toLocaleString() }}</template> |
| | | </el-table-column> |
| | | <el-table-column label="æªä»éé¢" prop="unpaidAmount" width="120"> |
| | | <template #default="{ row }">Â¥{{ row.unpaidAmount.toLocaleString() }}</template> |
| | | </el-table-column> |
| | | <el-table-column label="ææ¶äº¤è´§ç" prop="onTimeRate" width="120"> |
| | | <template #default="{ row }">{{ row.onTimeRate }}%</template> |
| | | </el-table-column> |
| | | <el-table-column label="è´¨éè¯å" prop="qualityRating" width="100"> |
| | | <template #default="{ row }"> |
| | | <el-rate v-model="row.qualityRating" disabled show-score text-color="#ff9900" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="åä½ç¶æ" prop="status" width="100"> |
| | | <template #default="{ row }"> |
| | | <el-tag :type="getSupplierStatusType(row.status)">{{ getSupplierStatusText(row.status) }}</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <PIMTable |
| | | :table-data="businessSummaryData" |
| | | :column="tableColumns" |
| | | :table-loading="loading" |
| | | :is-selection="false" |
| | | :border="true" |
| | | :is-show-pagination="true" |
| | | :page="page" |
| | | @pagination="handlePagination" |
| | | /> |
| | | </div> |
| | | </el-card> |
| | | </div> |
| | |
| | | <script setup> |
| | | import { ref, reactive, onMounted } from 'vue' |
| | | import { ElMessage } from 'element-plus' |
| | | import { Document, List, TrendCharts, Shop, Search, Refresh, Download } from '@element-plus/icons-vue' |
| | | import { Download } from '@element-plus/icons-vue' |
| | | import PIMTable from '@/components/PIMTable/PIMTable.vue' |
| | | import { procurementBusinessSummaryListPage } from '@/api/procurementManagement/procurementReport' |
| | | import { productTreeList } from '@/api/basicData/product' |
| | | |
| | | // ååºå¼æ°æ® |
| | | const loading = ref(false) |
| | | const activeReport = ref('orderSummary') |
| | | |
| | | // æç´¢è¡¨å |
| | | const searchForm = reactive({ |
| | | dateRange: [], |
| | | supplierId: '', |
| | | categoryId: '' |
| | | productCategory: '' |
| | | }) |
| | | |
| | | // ä¾åºåå表 |
| | | const supplierList = ref([ |
| | | { id: 1, name: 'æ±èåèçµåç§ææéå
¬å¸' }, |
| | | { id: 2, name: '䏿µ·ç²¾å¯æºæ¢°å¶é æéå
¬å¸' }, |
| | | { id: 3, name: 'æ·±å³æºè½è®¾å¤æéå
¬å¸' }, |
| | | { id: 4, name: 'åäº¬æ°ææç§ææéå
¬å¸' }, |
| | | { id: 5, name: '广å·çµåå
å¨ä»¶æéå
¬å¸' } |
| | | ]) |
| | | |
| | | // ååç±»å«å表 |
| | | const categoryList = ref([ |
| | | { id: 1, name: 'çµåå
å¨ä»¶' }, |
| | | { id: 2, name: 'æºæ¢°è®¾å¤' }, |
| | | { id: 3, name: 'åææ' }, |
| | | { id: 4, name: 'åå
¬ç¨å' }, |
| | | { id: 5, name: 'å
è£
ææ' } |
| | | ]) |
| | | // 产åç±»å«æ é项 |
| | | const productOptions = ref([]) |
| | | |
| | | // ç»è®¡æ°æ® |
| | | const orderSummaryStats = ref({ |
| | | totalOrders: 156, |
| | | totalAmount: 2580000, |
| | | completionRate: 87.5 |
| | | }) |
| | | |
| | | const orderDetailStats = ref({ |
| | | totalItems: 1248, |
| | | receivedItems: 1089, |
| | | pendingItems: 159 |
| | | }) |
| | | |
| | | const businessSummaryStats = ref({ |
| | | totalAmount: 2580000, |
| | | productTypes: 89, |
| | | supplierCount: 25 |
| | | totalAmount: 0, |
| | | productTypes: 0 |
| | | }) |
| | | |
| | | const supplierSummaryStats = ref({ |
| | | totalSuppliers: 25, |
| | | totalAmount: 2580000, |
| | | avgRating: 4.2 |
| | | }) |
| | | |
| | | // éè´è®¢åæ§è¡æ±æ»è¡¨æ°æ® |
| | | const orderSummaryData = ref([ |
| | | // è¡¨æ ¼åé
ç½®ï¼æ ¹æ®åç«¯åæ®µå®ä¹ï¼ |
| | | const tableColumns = ref([ |
| | | { |
| | | orderNo: 'PO20241201001', |
| | | supplierName: 'æ±èåèçµåç§ææéå
¬å¸', |
| | | orderDate: '2024-12-01', |
| | | plannedDelivery: '2024-12-15', |
| | | actualDelivery: '2024-12-14', |
| | | orderAmount: 125000, |
| | | paidAmount: 100000, |
| | | status: 'completed', |
| | | completionRate: 100, |
| | | delayDays: -1 |
| | | label: '产å大类', |
| | | prop: 'productCategory', |
| | | width: 150, |
| | | }, |
| | | { |
| | | orderNo: 'PO20241201002', |
| | | supplierName: '䏿µ·ç²¾å¯æºæ¢°å¶é æéå
¬å¸', |
| | | orderDate: '2024-12-02', |
| | | plannedDelivery: '2024-12-20', |
| | | actualDelivery: '2024-12-22', |
| | | orderAmount: 280000, |
| | | paidAmount: 140000, |
| | | status: 'partial', |
| | | completionRate: 75, |
| | | delayDays: 2 |
| | | label: 'è§æ ¼åå·', |
| | | prop: 'specificationModel', |
| | | width: 180 |
| | | }, |
| | | { |
| | | orderNo: 'PO20241201003', |
| | | supplierName: 'æ·±å³æºè½è®¾å¤æéå
¬å¸', |
| | | orderDate: '2024-12-03', |
| | | plannedDelivery: '2024-12-25', |
| | | actualDelivery: '', |
| | | orderAmount: 180000, |
| | | paidAmount: 0, |
| | | status: 'pending', |
| | | completionRate: 0, |
| | | delayDays: 0 |
| | | label: 'éè´æ°é', |
| | | prop: 'purchaseNum', |
| | | width: 120, |
| | | formatData: (val) => { |
| | | return val ? parseFloat(val).toLocaleString() : '0' |
| | | } |
| | | }, |
| | | { |
| | | orderNo: 'PO20241201004', |
| | | supplierName: 'åäº¬æ°ææç§ææéå
¬å¸', |
| | | orderDate: '2024-12-04', |
| | | plannedDelivery: '2024-12-18', |
| | | actualDelivery: '2024-12-18', |
| | | orderAmount: 95000, |
| | | paidAmount: 95000, |
| | | status: 'completed', |
| | | completionRate: 100, |
| | | delayDays: 0 |
| | | label: 'éè´éé¢', |
| | | prop: 'purchaseAmount', |
| | | width: 140, |
| | | formatData: (val) => { |
| | | return val ? `Â¥${parseFloat(val).toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}` : 'Â¥0.00' |
| | | } |
| | | }, |
| | | { |
| | | orderNo: 'PO20241201005', |
| | | supplierName: '广å·çµåå
å¨ä»¶æéå
¬å¸', |
| | | orderDate: '2024-12-05', |
| | | plannedDelivery: '2024-12-28', |
| | | actualDelivery: '', |
| | | orderAmount: 220000, |
| | | paidAmount: 0, |
| | | status: 'pending', |
| | | completionRate: 0, |
| | | delayDays: 0 |
| | | } |
| | | ]) |
| | | |
| | | // éè´è®¢åæ§è¡æç»è¡¨æ°æ® |
| | | const orderDetailData = ref([ |
| | | { |
| | | orderNo: 'PO20241201001', |
| | | productCode: 'EL001', |
| | | productName: 'çµé»å¨ 1KΩ ±5%', |
| | | specification: '1/4W 碳èçµé»', |
| | | unit: '个', |
| | | plannedQuantity: 1000, |
| | | receivedQuantity: 1000, |
| | | pendingQuantity: 0, |
| | | unitPrice: 0.15, |
| | | subtotal: 150, |
| | | status: 'completed', |
| | | lastReceiptDate: '2024-12-14' |
| | | label: 'éè´æ¬¡æ°', |
| | | prop: 'purchaseTimes', |
| | | width: 100 |
| | | }, |
| | | { |
| | | orderNo: 'PO20241201001', |
| | | productCode: 'EL002', |
| | | productName: 'çµå®¹å¨ 100μF', |
| | | specification: '25V éçµè§£çµå®¹', |
| | | unit: '个', |
| | | plannedQuantity: 500, |
| | | receivedQuantity: 500, |
| | | pendingQuantity: 0, |
| | | unitPrice: 0.85, |
| | | subtotal: 425, |
| | | status: 'completed', |
| | | lastReceiptDate: '2024-12-14' |
| | | label: 'å¹³ååä»·', |
| | | prop: 'averagePrice', |
| | | width: 120, |
| | | formatData: (val) => { |
| | | return val ? `Â¥${parseFloat(val).toFixed(2)}` : 'Â¥0.00' |
| | | } |
| | | }, |
| | | { |
| | | orderNo: 'PO20241201002', |
| | | productCode: 'ME001', |
| | | productName: 'ç²¾å¯è½´æ¿', |
| | | specification: '6205-2RS æ·±æ²çè½´æ¿', |
| | | unit: '个', |
| | | plannedQuantity: 200, |
| | | receivedQuantity: 150, |
| | | pendingQuantity: 50, |
| | | unitPrice: 25.5, |
| | | subtotal: 5100, |
| | | status: 'partial', |
| | | lastReceiptDate: '2024-12-20' |
| | | label: 'ä¾åºååç§°', |
| | | prop: 'supplierName', |
| | | width: 200 |
| | | }, |
| | | { |
| | | orderNo: 'PO20241201002', |
| | | productCode: 'ME002', |
| | | productName: 'ä¸éé¢èºä¸', |
| | | specification: 'M8Ã20 304ä¸éé¢', |
| | | unit: '个', |
| | | plannedQuantity: 1000, |
| | | receivedQuantity: 1000, |
| | | pendingQuantity: 0, |
| | | unitPrice: 0.8, |
| | | subtotal: 800, |
| | | status: 'completed', |
| | | lastReceiptDate: '2024-12-20' |
| | | }, |
| | | { |
| | | orderNo: 'PO20241201003', |
| | | productCode: 'SM001', |
| | | productName: 'æºè½ä¼ æå¨', |
| | | specification: 'æ¸©åº¦ä¼ æå¨ DS18B20', |
| | | unit: '个', |
| | | plannedQuantity: 300, |
| | | receivedQuantity: 0, |
| | | pendingQuantity: 300, |
| | | unitPrice: 12.5, |
| | | subtotal: 3750, |
| | | status: 'pending', |
| | | lastReceiptDate: '' |
| | | label: 'å½å
¥æ¥æ', |
| | | prop: 'entryDate', |
| | | width: 120 |
| | | } |
| | | ]) |
| | | |
| | | // éè´ä¸å¡æ±æ»è¡¨æ°æ® |
| | | const businessSummaryData = ref([ |
| | | { |
| | | category: 'çµåå
å¨ä»¶', |
| | | productCode: 'EL001', |
| | | productName: 'çµé»å¨ 1KΩ ±5%', |
| | | specification: '1/4W 碳èçµé»', |
| | | purchaseQuantity: 5000, |
| | | purchaseAmount: 750, |
| | | avgPrice: 0.15, |
| | | purchaseCount: 8, |
| | | mainSupplier: 'æ±èåèçµåç§ææéå
¬å¸', |
| | | lastPurchaseDate: '2024-12-01' |
| | | }, |
| | | { |
| | | category: 'çµåå
å¨ä»¶', |
| | | productCode: 'EL002', |
| | | productName: 'çµå®¹å¨ 100μF', |
| | | specification: '25V éçµè§£çµå®¹', |
| | | purchaseQuantity: 2500, |
| | | purchaseAmount: 2125, |
| | | avgPrice: 0.85, |
| | | purchaseCount: 6, |
| | | mainSupplier: 'æ±èåèçµåç§ææéå
¬å¸', |
| | | lastPurchaseDate: '2024-12-01' |
| | | }, |
| | | { |
| | | category: 'æºæ¢°è®¾å¤', |
| | | productCode: 'ME001', |
| | | productName: 'ç²¾å¯è½´æ¿', |
| | | specification: '6205-2RS æ·±æ²çè½´æ¿', |
| | | purchaseQuantity: 800, |
| | | purchaseAmount: 20400, |
| | | avgPrice: 25.5, |
| | | purchaseCount: 4, |
| | | mainSupplier: '䏿µ·ç²¾å¯æºæ¢°å¶é æéå
¬å¸', |
| | | lastPurchaseDate: '2024-12-02' |
| | | }, |
| | | { |
| | | category: 'æºæ¢°è®¾å¤', |
| | | productCode: 'ME002', |
| | | productName: 'ä¸éé¢èºä¸', |
| | | specification: 'M8Ã20 304ä¸éé¢', |
| | | purchaseQuantity: 5000, |
| | | purchaseAmount: 4000, |
| | | avgPrice: 0.8, |
| | | purchaseCount: 12, |
| | | mainSupplier: '䏿µ·ç²¾å¯æºæ¢°å¶é æéå
¬å¸', |
| | | lastPurchaseDate: '2024-12-02' |
| | | }, |
| | | { |
| | | category: 'æºè½è®¾å¤', |
| | | productCode: 'SM001', |
| | | productName: 'æºè½ä¼ æå¨', |
| | | specification: 'æ¸©åº¦ä¼ æå¨ DS18B20', |
| | | purchaseQuantity: 1200, |
| | | purchaseAmount: 15000, |
| | | avgPrice: 12.5, |
| | | purchaseCount: 5, |
| | | mainSupplier: 'æ·±å³æºè½è®¾å¤æéå
¬å¸', |
| | | lastPurchaseDate: '2024-12-03' |
| | | } |
| | | ]) |
| | | const businessSummaryData = ref([]) |
| | | |
| | | // ä¾åºåä¾è´§æ±æ»è¡¨æ°æ® |
| | | const supplierSummaryData = ref([ |
| | | { |
| | | supplierCode: 'SUP001', |
| | | supplierName: 'æ±èåèçµåç§ææéå
¬å¸', |
| | | contactPerson: 'å¼ ç»ç', |
| | | phone: '0512-88888888', |
| | | orderCount: 45, |
| | | supplyAmount: 850000, |
| | | paidAmount: 680000, |
| | | unpaidAmount: 170000, |
| | | onTimeRate: 95, |
| | | qualityRating: 4.5, |
| | | status: 'active' |
| | | }, |
| | | { |
| | | supplierCode: 'SUP002', |
| | | supplierName: '䏿µ·ç²¾å¯æºæ¢°å¶é æéå
¬å¸', |
| | | contactPerson: 'ææ»', |
| | | phone: '021-66666666', |
| | | orderCount: 32, |
| | | supplyAmount: 1200000, |
| | | paidAmount: 900000, |
| | | unpaidAmount: 300000, |
| | | onTimeRate: 88, |
| | | qualityRating: 4.2, |
| | | status: 'active' |
| | | }, |
| | | { |
| | | supplierCode: 'SUP003', |
| | | supplierName: 'æ·±å³æºè½è®¾å¤æéå
¬å¸', |
| | | contactPerson: 'çå·¥ç¨å¸', |
| | | phone: '0755-77777777', |
| | | orderCount: 28, |
| | | supplyAmount: 680000, |
| | | paidAmount: 400000, |
| | | unpaidAmount: 280000, |
| | | onTimeRate: 92, |
| | | qualityRating: 4.3, |
| | | status: 'active' |
| | | }, |
| | | { |
| | | supplierCode: 'SUP004', |
| | | supplierName: 'åäº¬æ°ææç§ææéå
¬å¸', |
| | | contactPerson: 'éå士', |
| | | phone: '010-55555555', |
| | | orderCount: 18, |
| | | supplyAmount: 320000, |
| | | paidAmount: 250000, |
| | | unpaidAmount: 70000, |
| | | onTimeRate: 85, |
| | | qualityRating: 4.0, |
| | | status: 'active' |
| | | }, |
| | | { |
| | | supplierCode: 'SUP005', |
| | | supplierName: '广å·çµåå
å¨ä»¶æéå
¬å¸', |
| | | contactPerson: 'åç»ç', |
| | | phone: '020-44444444', |
| | | orderCount: 22, |
| | | supplyAmount: 480000, |
| | | paidAmount: 200000, |
| | | unpaidAmount: 280000, |
| | | onTimeRate: 78, |
| | | qualityRating: 3.8, |
| | | status: 'warning' |
| | | } |
| | | ]) |
| | | // å页忰ï¼å端è¿åï¼total/size/current/pagesï¼ |
| | | const page = reactive({ |
| | | total: 0, |
| | | current: 1, |
| | | size: 50, |
| | | }) |
| | | |
| | | // æ¹æ³ |
| | | const handleReportChange = (tabName) => { |
| | | activeReport.value = tabName |
| | | handleSearch() |
| | | // 转æ¢äº§åæ æ°æ®ï¼å° id æ¹ä¸º value |
| | | function convertIdToValue(data) { |
| | | return data.map((item) => { |
| | | const { id, children, ...rest } = item |
| | | const newItem = { |
| | | ...rest, |
| | | value: id, |
| | | } |
| | | if (children && children.length > 0) { |
| | | newItem.children = convertIdToValue(children) |
| | | } |
| | | return newItem |
| | | }) |
| | | } |
| | | |
| | | const handleSearch = () => { |
| | | loading.value = true |
| | | // 模æAPIè°ç¨ |
| | | setTimeout(() => { |
| | | // è·å产åç±»å«æ æ°æ® |
| | | const getProductOptions = () => { |
| | | return productTreeList().then((res) => { |
| | | productOptions.value = convertIdToValue(res) |
| | | }).catch((error) => { |
| | | console.error('è·åäº§åæ å¤±è´¥:', error) |
| | | ElMessage.error('è·å产åç±»å«å¤±è´¥') |
| | | }) |
| | | } |
| | | |
| | | // æ ¹æ® id æ¥æ¾äº§åç±»å«åç§° |
| | | const findNodeLabelById = (nodes, id) => { |
| | | if (!id) return null |
| | | for (let i = 0; i < nodes.length; i++) { |
| | | if (nodes[i].value === id) { |
| | | return nodes[i].label |
| | | } |
| | | if (nodes[i].children && nodes[i].children.length > 0) { |
| | | const found = findNodeLabelById(nodes[i].children, id) |
| | | if (found) return found |
| | | } |
| | | } |
| | | return null |
| | | } |
| | | |
| | | // æ¥è¯¢å表 |
| | | const handleSearch = async () => { |
| | | try { |
| | | loading.value = true |
| | | const params = {} |
| | | |
| | | // æ¶é´èå´ |
| | | if (searchForm.dateRange && searchForm.dateRange.length === 2) { |
| | | params.entryDateStart = searchForm.dateRange[0] |
| | | params.entryDateEnd = searchForm.dateRange[1] |
| | | } |
| | | |
| | | // 产åç±»å« |
| | | if (searchForm.productCategory) { |
| | | const categoryName = findNodeLabelById(productOptions.value, searchForm.productCategory) |
| | | if (categoryName) { |
| | | params.productCategory = categoryName |
| | | } |
| | | } |
| | | |
| | | // å页忰 |
| | | params.current = page.current |
| | | params.size = page.size |
| | | |
| | | const res = await procurementBusinessSummaryListPage(params) |
| | | if (res && res.data) { |
| | | // å
¼å®¹å端å¯è½ç´æ¥è¿åæ°ç»/æè¿åå页对象 |
| | | businessSummaryData.value = Array.isArray(res.data) ? res.data : (res.data.records || []) |
| | | |
| | | if (!Array.isArray(res.data)) { |
| | | page.total = Number(res.data.total ?? 0) |
| | | page.current = Number(res.data.current ?? page.current) |
| | | page.size = Number(res.data.size ?? page.size) |
| | | } |
| | | |
| | | // 计ç®ç»è®¡æ°æ® |
| | | if (businessSummaryData.value.length > 0) { |
| | | businessSummaryStats.value.totalAmount = businessSummaryData.value.reduce((sum, item) => { |
| | | return sum + (parseFloat(item.purchaseAmount) || 0) |
| | | }, 0) |
| | | businessSummaryStats.value.productTypes = new Set(businessSummaryData.value.map(item => item.productCategory)).size |
| | | } else { |
| | | businessSummaryStats.value = { |
| | | totalAmount: 0, |
| | | productTypes: 0 |
| | | } |
| | | } |
| | | } |
| | | } catch (error) { |
| | | console.error('æ¥è¯¢å¤±è´¥:', error) |
| | | } finally { |
| | | loading.value = false |
| | | ElMessage.success('æ¥è¯¢å®æ') |
| | | }, 1000) |
| | | } |
| | | } |
| | | |
| | | // 翻页/忢æ¯é¡µæ¡æ° |
| | | const handlePagination = ({ page: current, limit }) => { |
| | | page.current = current |
| | | page.size = limit |
| | | handleSearch() |
| | | } |
| | | |
| | | const resetSearch = () => { |
| | | Object.assign(searchForm, { |
| | | dateRange: [], |
| | | supplierId: '', |
| | | categoryId: '' |
| | | productCategory: '' |
| | | }) |
| | | page.current = 1 |
| | | handleSearch() |
| | | } |
| | | |
| | |
| | | ElMessage.success('导åºåè½å¼åä¸...') |
| | | } |
| | | |
| | | // ç¶æç¸å
³æ¹æ³ |
| | | const getStatusType = (status) => { |
| | | const statusMap = { |
| | | completed: 'success', |
| | | partial: 'warning', |
| | | pending: 'info' |
| | | } |
| | | return statusMap[status] || 'info' |
| | | } |
| | | |
| | | const getStatusText = (status) => { |
| | | const statusMap = { |
| | | completed: '已宿', |
| | | partial: 'é¨å宿', |
| | | pending: 'å¾
æ§è¡' |
| | | } |
| | | return statusMap[status] || 'æªç¥' |
| | | } |
| | | |
| | | const getReceiptStatusType = (status) => { |
| | | const statusMap = { |
| | | completed: 'success', |
| | | partial: 'warning', |
| | | pending: 'info' |
| | | } |
| | | return statusMap[status] || 'info' |
| | | } |
| | | |
| | | const getReceiptStatusText = (status) => { |
| | | const statusMap = { |
| | | completed: 'å·²æ¶è´§', |
| | | partial: 'é¨åæ¶è´§', |
| | | pending: 'å¾
æ¶è´§' |
| | | } |
| | | return statusMap[status] || 'æªç¥' |
| | | } |
| | | |
| | | const getSupplierStatusType = (status) => { |
| | | const statusMap = { |
| | | active: 'success', |
| | | warning: 'warning', |
| | | inactive: 'info' |
| | | } |
| | | return statusMap[status] || 'info' |
| | | } |
| | | |
| | | const getSupplierStatusText = (status) => { |
| | | const statusMap = { |
| | | active: 'æ£å¸¸åä½', |
| | | warning: 'éå
³æ³¨', |
| | | inactive: 'æååä½' |
| | | } |
| | | return statusMap[status] || 'æªç¥' |
| | | } |
| | | |
| | | onMounted(() => { |
| | | // åå§å产åç±»å«æ |
| | | getProductOptions() |
| | | |
| | | // 设置é»è®¤æ¶é´èå´ä¸ºæè¿30天 |
| | | const endDate = new Date() |
| | | const startDate = new Date() |
| | |
| | | startDate.toISOString().split('T')[0], |
| | | endDate.toISOString().split('T')[0] |
| | | ] |
| | | |
| | | // åå§å è½½æ°æ® |
| | | handleSearch() |
| | | }) |
| | | </script> |
| | | |
| | |
| | | margin: 0; |
| | | font-size: 16px; |
| | | opacity: 0.9; |
| | | } |
| | | |
| | | .report-selector { |
| | | margin-bottom: 20px; |
| | | border-radius: 8px; |
| | | } |
| | | |
| | | .tab-label { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 8px; |
| | | } |
| | | |
| | | .search-card { |
| | | margin-bottom: 20px; |
| | | border-radius: 8px; |
| | | } |
| | | |
| | | .search-form { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | .report-content { |
| | |
| | | font-weight: 600; |
| | | } |
| | | |
| | | :deep(.el-table) { |
| | | border-radius: 8px; |
| | | overflow: hidden; |
| | | width: 100% !important; |
| | | } |
| | | |
| | | :deep(.el-table__body-wrapper) { |
| | | width: 100% !important; |
| | | } |
| | | |
| | | :deep(.el-table__header-wrapper) { |
| | | width: 100% !important; |
| | | } |
| | | |
| | | :deep(.el-table th) { |
| | | background-color: #f8f9fa; |
| | | color: #606266; |
| | | font-weight: 600; |
| | | } |
| | | |
| | | :deep(.el-table--striped .el-table__body tr.el-table__row--striped td) { |
| | | background-color: #fafafa; |
| | | } |
| | | |
| | | :deep(.el-tabs__header) { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | :deep(.el-tabs__nav-wrap) { |
| | | padding: 0 20px; |
| | | } |
| | | |
| | | :deep(.el-tabs__item) { |
| | | font-size: 16px; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | :deep(.el-tabs__item.is-active) { |
| | | color: #409EFF; |
| | | } |
| | | |
| | | :deep(.el-rate) { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | :deep(.el-rate__text) { |
| | | margin-left: 8px; |
| | | font-size: 14px; |
| | | color: #606266; |
| | | } |
| | | </style> |
| | |
| | | </el-table> |
| | | </el-card> |
| | | |
| | | <el-dialog v-model="dialogVisible" :title="dialogType === 'add' ? 'æ°å¢éè´è®¢å' : 'ç¼è¾éè´è®¢å'" width="800px"> |
| | | <FormDialog v-model="dialogVisible" :title="dialogType === 'add' ? 'æ°å¢éè´è®¢å' : 'ç¼è¾éè´è®¢å'" :width="'800px'" :operation-type="dialogType" @close="dialogVisible = false" @confirm="handleSubmit" @cancel="dialogVisible = false"> |
| | | <el-form :model="formData" ref="formRef" label-width="120px"> |
| | | <el-form-item label="ä¾åºååç§°" prop="supplierName"> |
| | | <el-select v-model="formData.supplierName" placeholder="è¯·éæ©ä¾åºå" style="width: 100%"> |
| | |
| | | <el-input v-model="formData.remark" type="textarea" :rows="3" placeholder="请è¾å
¥å¤æ³¨ä¿¡æ¯" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <el-button @click="dialogVisible = false">åæ¶</el-button> |
| | | <el-button type="primary" @click="handleSubmit">ç¡®å®</el-button> |
| | | </template> |
| | | </el-dialog> |
| | | </FormDialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import FormDialog from '@/components/Dialog/FormDialog.vue'; |
| | | import { ref, reactive } from 'vue' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | |
| src/views/procurementManagement/qualityInspection/index.vue
src/views/procurementManagement/returnManagement/index.vue
src/views/procurementManagement/transferManagement/index.vue
src/views/productManagement/productIdentifier/index.vue
src/views/productionManagement/operationScheduling/components/formDia.vue
src/views/productionManagement/operationScheduling/index.vue
src/views/productionManagement/processRoute/Edit.vue
src/views/productionManagement/processRoute/ItemsForm.vue
src/views/productionManagement/processRoute/New.vue
src/views/productionManagement/processRoute/index.vue
src/views/productionManagement/processRoute/processRouteItem/index.vue
src/views/productionManagement/productStructure/Detail/index.vue
src/views/productionManagement/productStructure/StructureEdit.vue
src/views/productionManagement/productStructure/index.vue
src/views/productionManagement/productionCosting/index.vue
src/views/productionManagement/productionDispatching/components/autoDispatchDia.vue
src/views/productionManagement/productionDispatching/components/formDia.vue
src/views/productionManagement/productionDispatching/index.vue
src/views/productionManagement/productionOrder/index.vue
src/views/productionManagement/productionProcess/Edit.vue
src/views/productionManagement/productionProcess/New.vue
src/views/productionManagement/productionProcess/index.vue
src/views/productionManagement/productionReporting/Input.vue
src/views/productionManagement/productionReporting/Output.vue
src/views/productionManagement/productionReporting/components/formDia.vue
src/views/productionManagement/productionReporting/index.vue
src/views/productionManagement/workOrder/index.vue
src/views/qualityManagement/finalInspection/components/filesDia.vue
src/views/qualityManagement/finalInspection/components/formDia.vue
src/views/qualityManagement/finalInspection/components/inspectionFormDia.vue
src/views/qualityManagement/metricBinding/index.vue
src/views/qualityManagement/metricMaintenance/ParamFormDialog.vue
src/views/qualityManagement/metricMaintenance/StandardFormDialog.vue
src/views/qualityManagement/metricMaintenance/index.vue
src/views/qualityManagement/metricMaintenance/index0.vue
src/views/qualityManagement/nonconformingManagement/components/formDia.vue
src/views/qualityManagement/nonconformingManagement/components/inspectionFormDia.vue
src/views/qualityManagement/processInspection/components/formDia.vue
src/views/qualityManagement/processInspection/components/inspectionFormDia.vue
src/views/qualityManagement/rawMaterialInspection/components/formDia.vue
src/views/qualityManagement/rawMaterialInspection/components/inspectionFormDia.vue
src/views/reportAnalysis/dataDashboard/index.vue
src/views/reportAnalysis/projectProfit/index.vue
src/views/reportAnalysis/reportManagement/index.vue
src/views/salesManagement/deliveryLedger/index.vue
src/views/salesManagement/indicatorStats/index.vue
src/views/salesManagement/invoiceLedger/index.vue
src/views/salesManagement/invoiceRegistration/index.vue
src/views/salesManagement/orderManagement/index.vue
src/views/salesManagement/paymentShipping/index.vue
src/views/salesManagement/receiptPayment/index.vue
src/views/salesManagement/receiptPaymentHistory/index.vue
src/views/salesManagement/receiptPaymentLedger/index.vue
src/views/salesManagement/salesLedger/fileList.vue
src/views/salesManagement/salesLedger/index.vue
src/views/salesManagement/salesQuotation/index.vue
src/views/salesManagement/salespersonManagement/index.vue
src/views/system/dept/index.vue
src/views/system/user/index.vue
vite.config.js |