Browse Source

new version

panxingxin 5 years ago
parent
commit
818ddfbfb3
100 changed files with 15959 additions and 0 deletions
  1. 36 0
      .gitignore
  2. BIN
      .gradle/5.6.2/executionHistory/executionHistory.bin
  3. BIN
      .gradle/5.6.2/executionHistory/executionHistory.lock
  4. BIN
      .gradle/5.6.2/fileChanges/last-build.bin
  5. BIN
      .gradle/5.6.2/fileHashes/fileHashes.lock
  6. 0 0
      .gradle/5.6.2/gc.properties
  7. BIN
      .gradle/buildOutputCleanup/buildOutputCleanup.lock
  8. 2 0
      .gradle/buildOutputCleanup/cache.properties
  9. 194 0
      angular.json
  10. 98 0
      config.xml
  11. 28 0
      e2e/protractor.conf.js
  12. 14 0
      e2e/src/app.e2e-spec.ts
  13. 11 0
      e2e/src/app.po.ts
  14. 13 0
      e2e/tsconfig.e2e.json
  15. 7 0
      ionic.config.json
  16. 11325 0
      package-lock.json
  17. 125 0
      package.json
  18. 33 0
      src/app/app-routing.module.ts
  19. 142 0
      src/app/app.component.html
  20. 47 0
      src/app/app.component.spec.ts
  21. 193 0
      src/app/app.component.ts
  22. 63 0
      src/app/app.module.ts
  23. 26 0
      src/app/bluetooth/bluetooth.module.ts
  24. 79 0
      src/app/bluetooth/bluetooth.page.html
  25. 19 0
      src/app/bluetooth/bluetooth.page.scss
  26. 27 0
      src/app/bluetooth/bluetooth.page.spec.ts
  27. 354 0
      src/app/bluetooth/bluetooth.page.ts
  28. 26 0
      src/app/contract-detail/contract-detail.module.ts
  29. 83 0
      src/app/contract-detail/contract-detail.page.html
  30. 6 0
      src/app/contract-detail/contract-detail.page.scss
  31. 27 0
      src/app/contract-detail/contract-detail.page.spec.ts
  32. 90 0
      src/app/contract-detail/contract-detail.page.ts
  33. 26 0
      src/app/contract-table/contract-table.module.ts
  34. 50 0
      src/app/contract-table/contract-table.page.html
  35. 0 0
      src/app/contract-table/contract-table.page.scss
  36. 27 0
      src/app/contract-table/contract-table.page.spec.ts
  37. 32 0
      src/app/contract-table/contract-table.page.ts
  38. 26 0
      src/app/contract/contract.module.ts
  39. 44 0
      src/app/contract/contract.page.html
  40. 0 0
      src/app/contract/contract.page.scss
  41. 27 0
      src/app/contract/contract.page.spec.ts
  42. 70 0
      src/app/contract/contract.page.ts
  43. 21 0
      src/app/drawTab/drawTab.module.ts
  44. 33 0
      src/app/drawTab/drawTab.page.html
  45. 4 0
      src/app/drawTab/drawTab.page.scss
  46. 26 0
      src/app/drawTab/drawTab.page.spec.ts
  47. 94 0
      src/app/drawTab/drawTab.page.ts
  48. 26 0
      src/app/enter-store/enter-store.module.ts
  49. 177 0
      src/app/enter-store/enter-store.page.html
  50. 0 0
      src/app/enter-store/enter-store.page.scss
  51. 27 0
      src/app/enter-store/enter-store.page.spec.ts
  52. 135 0
      src/app/enter-store/enter-store.page.ts
  53. 26 0
      src/app/infoTab/infoTab.module.ts
  54. 45 0
      src/app/infoTab/infoTab.page.html
  55. 18 0
      src/app/infoTab/infoTab.page.router.module.ts
  56. 12 0
      src/app/infoTab/infoTab.page.scss
  57. 27 0
      src/app/infoTab/infoTab.page.spec.ts
  58. 108 0
      src/app/infoTab/infoTab.page.ts
  59. 56 0
      src/app/login/login.page.html
  60. 23 0
      src/app/login/login.page.module.ts
  61. 23 0
      src/app/login/login.page.router.module.ts
  62. 11 0
      src/app/login/login.page.scss
  63. 88 0
      src/app/login/login.page.ts
  64. 29 0
      src/app/qc-popover/qc-popover.ts
  65. 30 0
      src/app/sample-detail/sample-detail.module.ts
  66. 110 0
      src/app/sample-detail/sample-detail.page.html
  67. 30 0
      src/app/sample-detail/sample-detail.page.scss
  68. 27 0
      src/app/sample-detail/sample-detail.page.spec.ts
  69. 102 0
      src/app/sample-detail/sample-detail.page.ts
  70. 26 0
      src/app/sample-table/sample-table.module.ts
  71. 71 0
      src/app/sample-table/sample-table.page.html
  72. 17 0
      src/app/sample-table/sample-table.page.scss
  73. 27 0
      src/app/sample-table/sample-table.page.spec.ts
  74. 33 0
      src/app/sample-table/sample-table.page.ts
  75. 26 0
      src/app/sample/sample.module.ts
  76. 53 0
      src/app/sample/sample.page.html
  77. 0 0
      src/app/sample/sample.page.scss
  78. 27 0
      src/app/sample/sample.page.spec.ts
  79. 83 0
      src/app/sample/sample.page.ts
  80. 26 0
      src/app/store-pending/store-pending.module.ts
  81. 31 0
      src/app/store-pending/store-pending.page.html
  82. 7 0
      src/app/store-pending/store-pending.page.scss
  83. 27 0
      src/app/store-pending/store-pending.page.spec.ts
  84. 33 0
      src/app/store-pending/store-pending.page.ts
  85. 26 0
      src/app/store-qc-detail/store-qc-detail.module.ts
  86. 132 0
      src/app/store-qc-detail/store-qc-detail.page.html
  87. 6 0
      src/app/store-qc-detail/store-qc-detail.page.scss
  88. 27 0
      src/app/store-qc-detail/store-qc-detail.page.spec.ts
  89. 130 0
      src/app/store-qc-detail/store-qc-detail.page.ts
  90. 26 0
      src/app/store-qc-scanning/store-qc-scanning.module.ts
  91. 138 0
      src/app/store-qc-scanning/store-qc-scanning.page.html
  92. 0 0
      src/app/store-qc-scanning/store-qc-scanning.page.scss
  93. 27 0
      src/app/store-qc-scanning/store-qc-scanning.page.spec.ts
  94. 158 0
      src/app/store-qc-scanning/store-qc-scanning.page.ts
  95. 26 0
      src/app/store-qc/store-qc.module.ts
  96. 29 0
      src/app/store-qc/store-qc.page.html
  97. 3 0
      src/app/store-qc/store-qc.page.scss
  98. 27 0
      src/app/store-qc/store-qc.page.spec.ts
  99. 39 0
      src/app/store-qc/store-qc.page.ts
  100. 0 0
      src/app/store-sample-barcode/store-sample-barcode.module.ts

+ 36 - 0
.gitignore

@@ -0,0 +1,36 @@
+# Specifies intentionally untracked files to ignore when using Git
+# http://git-scm.com/docs/gitignore
+
+*~
+*.sw[mnpcod]
+*.log
+*.tmp
+*.tmp.*
+log.txt
+*.sublime-project
+*.sublime-workspace
+.vscode/
+npm-debug.log*
+
+.idea/
+.ionic/
+.sourcemaps/
+.sass-cache/
+.tmp/
+.versions/
+coverage/
+www/
+node_modules/
+resources/
+platforms/
+tmp/
+temp/
+platforms/
+plugins/
+plugins/android.json
+plugins/ios.json
+$RECYCLE.BIN/
+
+.DS_Store
+Thumbs.db
+UserInterfaceState.xcuserstate

BIN
.gradle/5.6.2/executionHistory/executionHistory.bin


BIN
.gradle/5.6.2/executionHistory/executionHistory.lock


BIN
.gradle/5.6.2/fileChanges/last-build.bin


BIN
.gradle/5.6.2/fileHashes/fileHashes.lock


+ 0 - 0
.gradle/5.6.2/gc.properties


BIN
.gradle/buildOutputCleanup/buildOutputCleanup.lock


+ 2 - 0
.gradle/buildOutputCleanup/cache.properties

@@ -0,0 +1,2 @@
+#Fri Oct 18 10:45:15 CST 2019
+gradle.version=5.6.2

+ 194 - 0
angular.json

@@ -0,0 +1,194 @@
+{
+  "$schema": "./node_modules/@angular-devkit/core/src/workspace/workspace-schema.json",
+  "version": 1,
+  "defaultProject": "app",
+  "newProjectRoot": "projects",
+  "projects": {
+    "app": {
+      "root": "",
+      "sourceRoot": "src",
+      "projectType": "application",
+      "prefix": "app",
+      "schematics": {},
+      "architect": {
+        "build": {
+          "builder": "@angular-devkit/build-angular:browser",
+          "options": {
+            "outputPath": "www",
+            "index": "src/index.html",
+            "main": "src/main.ts",
+            "polyfills": "src/polyfills.ts",
+            "tsConfig": "src/tsconfig.app.json",
+            "assets": [
+              {
+                "glob": "**/*",
+                "input": "src/assets",
+                "output": "assets"
+              },
+              {
+                "glob": "**/*.svg",
+                "input": "node_modules/ionicons/dist/ionicons/svg",
+                "output": "./svg"
+              }
+            ],
+            "styles": [
+              {
+                "input": "src/theme/variables.scss"
+              },
+              {
+                "input": "src/global.scss"
+              }
+            ],
+            "scripts": [],
+            "es5BrowserSupport": true
+          },
+          "configurations": {
+            "production": {
+              "fileReplacements": [
+                {
+                  "replace": "src/environments/environment.ts",
+                  "with": "src/environments/environment.prod.ts"
+                }
+              ],
+              "optimization": true,
+              "outputHashing": "all",
+              "sourceMap": false,
+              "extractCss": true,
+              "namedChunks": false,
+              "aot": true,
+              "extractLicenses": true,
+              "vendorChunk": false,
+              "buildOptimizer": true,
+              "budgets": [
+                {
+                  "type": "initial",
+                  "maximumWarning": "2mb",
+                  "maximumError": "5mb"
+                }
+              ]
+            },
+            "ci": {
+              "progress": false
+            }
+          }
+        },
+        "serve": {
+          "builder": "@angular-devkit/build-angular:dev-server",
+          "options": {
+            "browserTarget": "app:build"
+          },
+          "configurations": {
+            "production": {
+              "browserTarget": "app:build:production"
+            },
+            "ci": {
+              "progress": false
+            }
+          }
+        },
+        "extract-i18n": {
+          "builder": "@angular-devkit/build-angular:extract-i18n",
+          "options": {
+            "browserTarget": "app:build"
+          }
+        },
+        "test": {
+          "builder": "@angular-devkit/build-angular:karma",
+          "options": {
+            "main": "src/test.ts",
+            "polyfills": "src/polyfills.ts",
+            "tsConfig": "src/tsconfig.spec.json",
+            "karmaConfig": "src/karma.conf.js",
+            "styles": [],
+            "scripts": [],
+            "assets": [
+              {
+                "glob": "favicon.ico",
+                "input": "src/",
+                "output": "/"
+              },
+              {
+                "glob": "**/*",
+                "input": "src/assets",
+                "output": "/assets"
+              }
+            ]
+          },
+          "configurations": {
+            "ci": {
+              "progress": false,
+              "watch": false
+            }
+          }
+        },
+        "lint": {
+          "builder": "@angular-devkit/build-angular:tslint",
+          "options": {
+            "tsConfig": ["src/tsconfig.app.json", "src/tsconfig.spec.json"],
+            "exclude": ["**/node_modules/**"]
+          }
+        },
+        "ionic-cordova-build": {
+          "builder": "@ionic/angular-toolkit:cordova-build",
+          "options": {
+            "browserTarget": "app:build"
+          },
+          "configurations": {
+            "production": {
+              "browserTarget": "app:build:production"
+            }
+          }
+        },
+        "ionic-cordova-serve": {
+          "builder": "@ionic/angular-toolkit:cordova-serve",
+          "options": {
+            "cordovaBuildTarget": "app:ionic-cordova-build",
+            "devServerTarget": "app:serve"
+          },
+          "configurations": {
+            "production": {
+              "cordovaBuildTarget": "app:ionic-cordova-build:production",
+              "devServerTarget": "app:serve:production"
+            }
+          }
+        }
+      }
+    },
+    "app-e2e": {
+      "root": "e2e/",
+      "projectType": "application",
+      "architect": {
+        "e2e": {
+          "builder": "@angular-devkit/build-angular:protractor",
+          "options": {
+            "protractorConfig": "e2e/protractor.conf.js",
+            "devServerTarget": "app:serve"
+          },
+          "configurations": {
+            "ci": {
+              "devServerTarget": "app:serve:ci"
+            }
+          }
+        },
+        "lint": {
+          "builder": "@angular-devkit/build-angular:tslint",
+          "options": {
+            "tsConfig": "e2e/tsconfig.e2e.json",
+            "exclude": ["**/node_modules/**"]
+          }
+        }
+      }
+    }
+  },
+  "cli": {
+    "defaultCollection": "@ionic/angular-toolkit"
+  },
+  "schematics": {
+    "@ionic/angular-toolkit:component": {
+      "styleext": "scss"
+    },
+    "@ionic/angular-toolkit:page": {
+      "styleext": "scss"
+    }
+  }
+}

+ 98 - 0
config.xml

@@ -0,0 +1,98 @@
+<?xml version='1.0' encoding='utf-8'?>
+<widget id="io.ionic.starter" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
+    <name>MyApp</name>
+    <description>An awesome Ionic/Cordova app.</description>
+    <author email="hi@ionicframework.com" href="http://ionicframework.com/">Ionic Framework Team</author>
+    <content src="index.html" />
+    <access origin="*" />
+    <allow-intent href="http://*/*" />
+    <allow-intent href="https://*/*" />
+    <allow-intent href="tel:*" />
+    <allow-intent href="sms:*" />
+    <allow-intent href="mailto:*" />
+    <allow-intent href="geo:*" />
+    <preference name="ScrollEnabled" value="false" />
+    <preference name="android-minSdkVersion" value="19" />
+    <preference name="BackupWebStorage" value="none" />
+    <preference name="SplashMaintainAspectRatio" value="true" />
+    <preference name="FadeSplashScreenDuration" value="300" />
+    <preference name="SplashShowOnlyFirstTime" value="false" />
+    <preference name="SplashScreen" value="screen" />
+    <preference name="SplashScreenDelay" value="3000" />
+    <platform name="android">
+        <allow-intent href="market:*" />
+        <icon density="ldpi" src="resources/android/icon/drawable-ldpi-icon.png" />
+        <icon density="mdpi" src="resources/android/icon/drawable-mdpi-icon.png" />
+        <icon density="hdpi" src="resources/android/icon/drawable-hdpi-icon.png" />
+        <icon density="xhdpi" src="resources/android/icon/drawable-xhdpi-icon.png" />
+        <icon density="xxhdpi" src="resources/android/icon/drawable-xxhdpi-icon.png" />
+        <icon density="xxxhdpi" src="resources/android/icon/drawable-xxxhdpi-icon.png" />
+        <splash density="land-ldpi" src="resources/android/splash/drawable-land-ldpi-screen.png" />
+        <splash density="land-mdpi" src="resources/android/splash/drawable-land-mdpi-screen.png" />
+        <splash density="land-hdpi" src="resources/android/splash/drawable-land-hdpi-screen.png" />
+        <splash density="land-xhdpi" src="resources/android/splash/drawable-land-xhdpi-screen.png" />
+        <splash density="land-xxhdpi" src="resources/android/splash/drawable-land-xxhdpi-screen.png" />
+        <splash density="land-xxxhdpi" src="resources/android/splash/drawable-land-xxxhdpi-screen.png" />
+        <splash density="port-ldpi" src="resources/android/splash/drawable-port-ldpi-screen.png" />
+        <splash density="port-mdpi" src="resources/android/splash/drawable-port-mdpi-screen.png" />
+        <splash density="port-hdpi" src="resources/android/splash/drawable-port-hdpi-screen.png" />
+        <splash density="port-xhdpi" src="resources/android/splash/drawable-port-xhdpi-screen.png" />
+        <splash density="port-xxhdpi" src="resources/android/splash/drawable-port-xxhdpi-screen.png" />
+        <splash density="port-xxxhdpi" src="resources/android/splash/drawable-port-xxxhdpi-screen.png" />
+    </platform>
+    <platform name="ios">
+        <allow-intent href="itms:*" />
+        <allow-intent href="itms-apps:*" />
+        <icon height="57" src="resources/ios/icon/icon.png" width="57" />
+        <icon height="114" src="resources/ios/icon/icon@2x.png" width="114" />
+        <icon height="29" src="resources/ios/icon/icon-small.png" width="29" />
+        <icon height="58" src="resources/ios/icon/icon-small@2x.png" width="58" />
+        <icon height="87" src="resources/ios/icon/icon-small@3x.png" width="87" />
+        <icon height="20" src="resources/ios/icon/icon-20.png" width="20" />
+        <icon height="40" src="resources/ios/icon/icon-20@2x.png" width="40" />
+        <icon height="60" src="resources/ios/icon/icon-20@3x.png" width="60" />
+        <icon height="48" src="resources/ios/icon/icon-24@2x.png" width="48" />
+        <icon height="55" src="resources/ios/icon/icon-27.5@2x.png" width="55" />
+        <icon height="29" src="resources/ios/icon/icon-29.png" width="29" />
+        <icon height="58" src="resources/ios/icon/icon-29@2x.png" width="58" />
+        <icon height="87" src="resources/ios/icon/icon-29@3x.png" width="87" />
+        <icon height="40" src="resources/ios/icon/icon-40.png" width="40" />
+        <icon height="80" src="resources/ios/icon/icon-40@2x.png" width="80" />
+        <icon height="120" src="resources/ios/icon/icon-40@3x.png" width="120" />
+        <icon height="88" src="resources/ios/icon/icon-44@2x.png" width="88" />
+        <icon height="50" src="resources/ios/icon/icon-50.png" width="50" />
+        <icon height="100" src="resources/ios/icon/icon-50@2x.png" width="100" />
+        <icon height="60" src="resources/ios/icon/icon-60.png" width="60" />
+        <icon height="120" src="resources/ios/icon/icon-60@2x.png" width="120" />
+        <icon height="180" src="resources/ios/icon/icon-60@3x.png" width="180" />
+        <icon height="72" src="resources/ios/icon/icon-72.png" width="72" />
+        <icon height="144" src="resources/ios/icon/icon-72@2x.png" width="144" />
+        <icon height="76" src="resources/ios/icon/icon-76.png" width="76" />
+        <icon height="152" src="resources/ios/icon/icon-76@2x.png" width="152" />
+        <icon height="167" src="resources/ios/icon/icon-83.5@2x.png" width="167" />
+        <icon height="172" src="resources/ios/icon/icon-86@2x.png" width="172" />
+        <icon height="196" src="resources/ios/icon/icon-98@2x.png" width="196" />
+        <icon height="1024" src="resources/ios/icon/icon-1024.png" width="1024" />
+        <splash height="480" src="resources/ios/splash/Default~iphone.png" width="320" />
+        <splash height="960" src="resources/ios/splash/Default@2x~iphone.png" width="640" />
+        <splash height="1024" src="resources/ios/splash/Default-Portrait~ipad.png" width="768" />
+        <splash height="768" src="resources/ios/splash/Default-Landscape~ipad.png" width="1024" />
+        <splash height="1125" src="resources/ios/splash/Default-Landscape-2436h.png" width="2436" />
+        <splash height="1242" src="resources/ios/splash/Default-Landscape-736h.png" width="2208" />
+        <splash height="2048" src="resources/ios/splash/Default-Portrait@2x~ipad.png" width="1536" />
+        <splash height="1536" src="resources/ios/splash/Default-Landscape@2x~ipad.png" width="2048" />
+        <splash height="2732" src="resources/ios/splash/Default-Portrait@~ipadpro.png" width="2048" />
+        <splash height="2048" src="resources/ios/splash/Default-Landscape@~ipadpro.png" width="2732" />
+        <splash height="1136" src="resources/ios/splash/Default-568h@2x~iphone.png" width="640" />
+        <splash height="1334" src="resources/ios/splash/Default-667h.png" width="750" />
+        <splash height="2208" src="resources/ios/splash/Default-736h.png" width="1242" />
+        <splash height="2436" src="resources/ios/splash/Default-2436h.png" width="1125" />
+        <splash height="2732" src="resources/ios/splash/Default@2x~universal~anyany.png" width="2732" />
+    </platform>
+    <plugin name="cordova-plugin-whitelist" spec="1.3.3" />
+    <plugin name="cordova-plugin-statusbar" spec="2.4.2" />
+    <plugin name="cordova-plugin-device" spec="2.0.2" />
+    <plugin name="cordova-plugin-splashscreen" spec="5.0.2" />
+    <plugin name="cordova-plugin-ionic-webview" spec="^4.0.0" />
+    <plugin name="cordova-plugin-ionic-keyboard" spec="^2.0.5" />
+</widget>

+ 28 - 0
e2e/protractor.conf.js

@@ -0,0 +1,28 @@
+// Protractor configuration file, see link for more information
+// https://github.com/angular/protractor/blob/master/lib/config.ts
+
+const { SpecReporter } = require('jasmine-spec-reporter');
+
+exports.config = {
+  allScriptsTimeout: 11000,
+  specs: [
+    './src/**/*.e2e-spec.ts'
+  ],
+  capabilities: {
+    'browserName': 'chrome'
+  },
+  directConnect: true,
+  baseUrl: 'http://localhost:4200/',
+  framework: 'jasmine',
+  jasmineNodeOpts: {
+    showColors: true,
+    defaultTimeoutInterval: 30000,
+    print: function() {}
+  },
+  onPrepare() {
+    require('ts-node').register({
+      project: require('path').join(__dirname, './tsconfig.e2e.json')
+    });
+    jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
+  }
+};

+ 14 - 0
e2e/src/app.e2e-spec.ts

@@ -0,0 +1,14 @@
+import { AppPage } from './app.po';
+
+describe('new App', () => {
+  let page: AppPage;
+
+  beforeEach(() => {
+    page = new AppPage();
+  });
+
+  it('should display welcome message', () => {
+    page.navigateTo();
+    expect(page.getPageTitle()).toContain('Tab One');
+  });
+});

+ 11 - 0
e2e/src/app.po.ts

@@ -0,0 +1,11 @@
+import { browser, by, element } from 'protractor';
+
+export class AppPage {
+  navigateTo() {
+    return browser.get('/');
+  }
+
+  getPageTitle() {
+    return element(by.css('ion-title')).getText();
+  }
+}

+ 13 - 0
e2e/tsconfig.e2e.json

@@ -0,0 +1,13 @@
+{
+  "extends": "../tsconfig.json",
+  "compilerOptions": {
+    "outDir": "../out-tsc/app",
+    "module": "commonjs",
+    "target": "es5",
+    "types": [
+      "jasmine",
+      "jasminewd2",
+      "node"
+    ]
+  }
+}

+ 7 - 0
ionic.config.json

@@ -0,0 +1,7 @@
+{
+  "name": "myAndroid",
+  "integrations": {
+    "cordova": {}
+  },
+  "type": "angular"
+}

File diff suppressed because it is too large
+ 11325 - 0
package-lock.json


+ 125 - 0
package.json

@@ -0,0 +1,125 @@
+{
+  "name": "myAndroid",
+  "version": "0.0.1",
+  "author": "Ionic Framework",
+  "homepage": "https://ionicframework.com/",
+  "scripts": {
+    "ng": "ng",
+    "start": "ng serve",
+    "build": "ng build",
+    "test": "ng test",
+    "lint": "ng lint",
+    "e2e": "ng e2e"
+  },
+  "private": true,
+  "dependencies": {
+    "@angular/common": "^7.2.2",
+    "@angular/core": "^7.2.2",
+    "@angular/forms": "^7.2.2",
+    "@angular/http": "^7.2.2",
+    "@angular/platform-browser": "^7.2.2",
+    "@angular/platform-browser-dynamic": "^7.2.2",
+    "@angular/router": "^7.2.2",
+    "@ionic-native/app-update": "^5.16.0",
+    "@ionic-native/app-version": "^5.16.0",
+    "@ionic-native/bluetooth-le": "^5.15.1",
+    "@ionic-native/bluetooth-serial": "^5.15.1",
+    "@ionic-native/camera": "^5.5.1",
+    "@ionic-native/core": "^5.0.0",
+    "@ionic-native/device": "^5.16.0",
+    "@ionic-native/downloader": "^5.16.0",
+    "@ionic-native/file": "^5.16.0",
+    "@ionic-native/file-opener": "^5.16.0",
+    "@ionic-native/file-transfer": "^5.16.0",
+    "@ionic-native/full-screen-image": "^5.16.0",
+    "@ionic-native/http": "^5.6.0",
+    "@ionic-native/keyboard": "^5.9.0",
+    "@ionic-native/local-notifications": "^5.16.0",
+    "@ionic-native/splash-screen": "^5.0.0",
+    "@ionic-native/status-bar": "^5.0.0",
+    "@ionic/angular": "^4.1.0",
+    "@ionic/storage": "^2.2.0",
+    "cordova-android": "8.0.0",
+    "cordova-browser": "6.0.0",
+    "cordova-plugin-advanced-http": "2.0.9",
+    "cordova-plugin-app-version": "^0.1.9",
+    "cordova-plugin-badge": "^0.8.8",
+    "cordova-plugin-bluetooth-serial": "^0.4.7",
+    "cordova-plugin-bluetoothle": "^4.5.5",
+    "cordova-plugin-camera": "4.0.3",
+    "cordova-plugin-file": "6.0.1",
+    "cordova-plugin-file-opener2": "^2.2.1",
+    "cordova-plugin-file-transfer": "^1.7.1",
+    "cordova-plugin-local-notification": "^0.9.0-beta.2",
+    "cordova-sqlite-storage": "3.2.0",
+    "core-js": "^2.5.4",
+    "crypto-js": "^3.1.9-1",
+    "es.keensoft.fullscreenimage": "^0.2.10",
+    "hammerjs": "^2.0.8",
+    "rxjs": "~6.5.1",
+    "tslib": "^1.9.0",
+    "zone.js": "~0.8.29"
+  },
+  "devDependencies": {
+    "@angular-devkit/architect": "~0.13.8",
+    "@angular-devkit/build-angular": "~0.13.8",
+    "@angular-devkit/core": "~7.3.8",
+    "@angular-devkit/schematics": "~7.3.8",
+    "@angular/cli": "7.3.9",
+    "@angular/compiler": "~7.2.2",
+    "@angular/compiler-cli": "~7.2.2",
+    "@angular/language-service": "~7.2.2",
+    "@ionic/angular-toolkit": "~1.5.1",
+    "@types/jasmine": "~2.8.8",
+    "@types/jasminewd2": "~2.0.3",
+    "@types/node": "~12.0.0",
+    "codelyzer": "~4.5.0",
+    "cordova-plugin-device": "2.0.2",
+    "cordova-plugin-ionic-keyboard": "^2.0.5",
+    "cordova-plugin-ionic-webview": "^4.0.0",
+    "cordova-plugin-splashscreen": "5.0.2",
+    "cordova-plugin-statusbar": "2.4.2",
+    "cordova-plugin-whitelist": "1.3.3",
+    "jasmine-core": "~2.99.1",
+    "jasmine-spec-reporter": "~4.2.1",
+    "karma": "~4.1.0",
+    "karma-chrome-launcher": "~2.2.0",
+    "karma-coverage-istanbul-reporter": "~2.0.1",
+    "karma-jasmine": "~1.1.2",
+    "karma-jasmine-html-reporter": "^0.2.2",
+    "protractor": "~5.4.0",
+    "ts-node": "~8.1.0",
+    "tslint": "~5.16.0",
+    "typescript": "~3.1.6"
+  },
+  "description": "An Ionic project",
+  "cordova": {
+    "plugins": {
+      "cordova-plugin-whitelist": {},
+      "cordova-plugin-statusbar": {},
+      "cordova-plugin-device": {},
+      "cordova-plugin-splashscreen": {},
+      "cordova-plugin-ionic-webview": {
+        "ANDROID_SUPPORT_ANNOTATIONS_VERSION": "27.+"
+      },
+      "cordova-plugin-ionic-keyboard": {},
+      "cordova-plugin-camera": {},
+      "cordova-sqlite-storage": {},
+      "cordova-plugin-advanced-http": {},
+      "cordova-plugin-bluetoothle": {},
+      "cordova-plugin-bluetooth-serial": {},
+      "cordova-plugin-local-notification": {},
+      "es.keensoft.fullscreenimage": {},
+      "cordova-plugin-app-version": {},
+      "cordova-plugin-file-opener2": {
+        "ANDROID_SUPPORT_V4_VERSION": "27.+"
+      },
+      "cordova-plugin-file-transfer": {},
+      "cordova-plugin-file": {}
+    },
+    "platforms": [
+      "browser",
+      "android"
+    ]
+  }
+}

+ 33 - 0
src/app/app-routing.module.ts

@@ -0,0 +1,33 @@
+import { NgModule } from '@angular/core';
+import { PreloadAllModules, RouterModule, Routes } from '@angular/router';
+import { LoginGuardGuard } from '../guard/login-guard.guard';
+
+const routes: Routes = [
+  { path: '', loadChildren: './login/login.page.module#LoginPageModule' },
+  { path: '', loadChildren: './tabs/tabs.module#TabsPageModule', canActivate: [LoginGuardGuard] },
+  // { path: '', loadChildren: './store-sample-tabs/store-sample-tabs.module#StoreSampleTabsPageModule', canActivate: [LoginGuardGuard]  },
+  { path: 'sample', loadChildren: './sample/sample.module#SamplePageModule' },
+  { path: 'sample-detail', loadChildren: './sample-detail/sample-detail.module#SampleDetailPageModule' },
+  { path: 'sample-table', loadChildren: './sample-table/sample-table.module#SampleTablePageModule' },
+  { path: 'contract', loadChildren: './contract/contract.module#ContractPageModule' },
+  { path: 'contract-table', loadChildren: './contract-table/contract-table.module#ContractTablePageModule' },
+  { path: 'contract-detail', loadChildren: './contract-detail/contract-detail.module#ContractDetailPageModule' },
+  { path: 'enter-store', loadChildren: './enter-store/enter-store.module#EnterStorePageModule' },
+  { path: 'store-sample', loadChildren: './store-sample/store-sample.module#StoreSamplePageModule' },
+  { path: 'store-sample-barcode', loadChildren: './store-sample-barcode/store-sample-barcode.module#StoreSampleBarcodePageModule' },
+  // { path: 'bluetooth', loadChildren: './bluetooth/bluetooth.module#BluetoothPageModule' },
+  { path: 'store-sample-binding', loadChildren: './store-sample-binding/store-sample-binding.module#StoreSampleBindingPageModule' },
+  { path: 'store-pending', loadChildren: './store-pending/store-pending.module#StorePendingPageModule' },
+  { path: 'store-qc', loadChildren: './store-qc/store-qc.module#StoreQCPageModule' },
+  { path: 'store-qc-detail', loadChildren: './store-qc-detail/store-qc-detail.module#StoreQCDetailPageModule' },
+  { path: 'store-qc-scanning', loadChildren: './store-qc-scanning/store-qc-scanning.module#StoreQCScanningPageModule' },
+  { path: 'store-sample-pending', loadChildren: './store-sample-pending/store-sample-pending.module#StoreSamplePendingPageModule' }
+  // { path: 'scanning', loadChildren: './scanning/scanning.module#ScanningPageModule', canActivate: [LoginGuardGuard] }
+];
+@NgModule({
+  imports: [
+    RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules })
+  ],
+  exports: [RouterModule]
+})
+export class AppRoutingModule {}

+ 142 - 0
src/app/app.component.html

@@ -0,0 +1,142 @@
+<ion-app>
+  <ion-split-pane>
+    <ion-menu menuId="leftMenu">
+      <ion-header>
+        <ion-toolbar>
+          <ion-title>菜 单</ion-title>
+        </ion-toolbar>
+      </ion-header>
+      <ion-content>
+        <ion-list>
+          <ion-list-header>
+            账户
+          </ion-list-header>
+          <ion-menu-toggle autoHide="false">
+            <ion-item routerLink="/login">
+              <ion-icon slot="start" name="log-in"></ion-icon>
+              <ion-label>
+                登录
+              </ion-label>
+            </ion-item>
+          </ion-menu-toggle>
+          <ion-menu-toggle autoHide="false">
+            <ion-item button (click)="logout()">
+              <ion-icon slot="start" name="log-out"></ion-icon>
+              <ion-label>
+                登出
+              </ion-label>
+            </ion-item>
+          </ion-menu-toggle>
+
+        </ion-list>
+
+        <ion-list *ngIf="loggedIn">
+        <!-- <ion-list> -->
+          <ion-list-header>
+            业务
+          </ion-list-header>
+
+          <ion-menu-toggle autoHide="false">
+            <ion-item routerLink="/scanning">
+              <ion-icon slot="start" name="qr-scanner"></ion-icon>
+              <ion-label>
+                开单号,样品扫描
+              </ion-label>
+            </ion-item>
+          </ion-menu-toggle>
+
+          <ion-menu-toggle autoHide="false">
+            <ion-item routerLink="/sample">
+              <ion-icon slot="start" name="document"></ion-icon>
+              <ion-label>
+                样品单管理
+              </ion-label>
+            </ion-item>
+          </ion-menu-toggle>
+
+          <ion-menu-toggle autoHide="false">
+            <ion-item routerLink="/store-sample-pending">
+              <ion-icon slot="start" name="timer"></ion-icon>
+              <ion-label>
+                待备样
+              </ion-label>
+            </ion-item>
+          </ion-menu-toggle>
+
+          <ion-menu-toggle autoHide="false">
+            <ion-item routerLink="/contract">
+              <ion-icon slot="start" name="book"></ion-icon>
+              <ion-label>
+                采购合同
+              </ion-label>
+            </ion-item>
+          </ion-menu-toggle>
+
+          <ion-menu-toggle autoHide="false">
+            <ion-item routerLink="/enter-store">
+              <ion-icon slot="start" name="appstore"></ion-icon>
+              <ion-label>
+                入库单
+              </ion-label>
+            </ion-item>
+          </ion-menu-toggle>
+
+
+          <ion-menu-toggle autoHide="false">
+            <ion-item routerLink="/store-sample">
+              <ion-icon slot="start" name="home"></ion-icon>
+              <ion-label>
+                仓库样品
+              </ion-label>
+            </ion-item>
+          </ion-menu-toggle>
+        </ion-list>
+
+        <ion-list *ngIf="loggedIn">
+          <ion-list-header>
+            QC
+          </ion-list-header>
+          <ion-menu-toggle autoHide="false">
+            <ion-item routerLink="/store-qc">
+              <ion-icon slot="start" name="list-box"></ion-icon>
+              <ion-label>
+                QC验货初检报告列表
+              </ion-label>
+            </ion-item>
+          </ion-menu-toggle>
+          <ion-menu-toggle autoHide="false">
+            <ion-item routerLink="/store-qc-scanning">
+              <ion-icon slot="start" name="qr-scanner"></ion-icon>
+              <ion-label>
+                QC扫描
+              </ion-label>
+            </ion-item>
+          </ion-menu-toggle>
+          <ion-menu-toggle autoHide="false">
+            <ion-item routerLink="/store-pending">
+              <ion-icon slot="start" name="checkbox"></ion-icon>
+              <ion-label>
+                待验货物
+              </ion-label>
+            </ion-item>
+          </ion-menu-toggle>
+        </ion-list>
+        <!-- <ion-list>
+          <ion-list-header>
+            Tutorial
+          </ion-list-header>
+          <ion-menu-toggle autoHide="false">
+            <ion-item button (click)="openTutorial()">
+              <ion-icon slot="start" name="hammer"></ion-icon>
+              <ion-label>Show Tutorial</ion-label>
+            </ion-item>
+          </ion-menu-toggle>
+        </ion-list> -->
+      </ion-content>
+    </ion-menu>
+
+    <ion-router-outlet main></ion-router-outlet>
+
+  </ion-split-pane>
+
+</ion-app>

+ 47 - 0
src/app/app.component.spec.ts

@@ -0,0 +1,47 @@
+import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
+import { TestBed, async } from '@angular/core/testing';
+
+import { Platform } from '@ionic/angular';
+import { SplashScreen } from '@ionic-native/splash-screen/ngx';
+import { StatusBar } from '@ionic-native/status-bar/ngx';
+
+import { AppComponent } from './app.component';
+
+describe('AppComponent', () => {
+
+  let statusBarSpy, splashScreenSpy, platformReadySpy, platformSpy;
+
+  beforeEach(async(() => {
+    statusBarSpy = jasmine.createSpyObj('StatusBar', ['styleDefault']);
+    splashScreenSpy = jasmine.createSpyObj('SplashScreen', ['hide']);
+    platformReadySpy = Promise.resolve();
+    platformSpy = jasmine.createSpyObj('Platform', { ready: platformReadySpy });
+
+    TestBed.configureTestingModule({
+      declarations: [AppComponent],
+      schemas: [CUSTOM_ELEMENTS_SCHEMA],
+      providers: [
+        { provide: StatusBar, useValue: statusBarSpy },
+        { provide: SplashScreen, useValue: splashScreenSpy },
+        { provide: Platform, useValue: platformSpy },
+      ],
+    }).compileComponents();
+  }));
+
+  it('should create the app', () => {
+    const fixture = TestBed.createComponent(AppComponent);
+    const app = fixture.debugElement.componentInstance;
+    expect(app).toBeTruthy();
+  });
+
+  it('should initialize the app', async () => {
+    TestBed.createComponent(AppComponent);
+    expect(platformSpy.ready).toHaveBeenCalled();
+    await platformReadySpy;
+    expect(statusBarSpy.styleDefault).toHaveBeenCalled();
+    expect(splashScreenSpy.hide).toHaveBeenCalled();
+  });
+
+  // TODO: add more tests!
+
+});

+ 193 - 0
src/app/app.component.ts

@@ -0,0 +1,193 @@
+import { Component } from '@angular/core';
+
+import { Platform, Events, AlertController } from '@ionic/angular';
+import { SplashScreen } from '@ionic-native/splash-screen/ngx';
+import { StatusBar } from '@ionic-native/status-bar/ngx';
+import { Storage } from '@ionic/storage'
+import { UserData } from '../providers/user-data';
+import { Router } from '@angular/router';
+import { LocalNotifications } from '@ionic-native/local-notifications/ngx';
+// import { FileOpener } from '@ionic-native/file-opener/ngx';
+// import { FileTransfer } from '@ionic-native/file-transfer/ngx'; 
+import { AppVersion } from '@ionic-native/app-version/ngx'; 
+// import { File } from '@ionic-native/file/ngx';
+import { WebSocketService } from '../providers/WebSocketService';
+import { Device } from '@ionic-native/device/ngx';
+import { Update } from '../providers/update'
+
+@Component({
+  selector: 'app-root',
+  templateUrl: 'app.component.html'
+})
+export class AppComponent {
+  private access_token: string
+  private loggedIn: boolean = false;
+  constructor(
+    private device: Device,
+    private localNotifications: LocalNotifications,
+    private router: Router,
+    private appVersion: AppVersion,
+    private events: Events,
+    private update: Update,
+    private userData: UserData,
+    private storage: Storage,
+    private platform: Platform,
+    private alertController: AlertController,
+    private splashScreen: SplashScreen,
+    private statusBar: StatusBar,
+    private wsService: WebSocketService
+  ) {
+    this.initializeApp();
+    // this.update.isUpdate()
+    this.backButtonEvent()
+  }
+  ngOnInit() {
+    this.initWebSocket()
+    //WS连接的IP和端口提前保存在localStorage里,现在读出来
+    // this.wsService.createObservableSocket(`ws://192.168.20.32:8804/websocket/403`);
+    // this.wsService.sendMessage('testhis.fullScreenImaget')
+    // this.getScanCode()
+    this.checkLoginStatus()
+    this.listenForLoginEvents()
+  }
+
+  getUserId(): Promise<string> {
+    return this.storage.get('user_id').then((value) => {
+      return value;
+    });
+  }
+
+  async initWebSocket() {
+    let _this = this
+    let user_id = await this.getUserId()
+    if (user_id) {
+      let wsUrl = `ws://dev.sgsino.cn/websocket/${user_id}`
+      let ws = new WebSocket(wsUrl)
+      ws.onopen = function (evt) {
+      }
+      ws.onmessage = function (evt) {
+        _this.localNotifications.schedule({
+          text: evt.data,
+          // trigger: {at: new Date(new Date().getTime() + 3600)},
+          led: 'FF0000',
+          sound: _this.device.platform == 'Android' ? 'file://sound.mp3' : 'file://beep.caf',
+        });
+      }
+    }
+  }
+
+  // ngAfterContentInit() {
+  //   this.appVersion.getVersionNumber().then((value: any) => {
+  //     console.log(value)
+  //   })
+  // }
+  ionViewDidLoad() {
+  }
+
+  getScanCode() {
+    let _this = this
+    let lastTime = null;
+    let nextTime = null;
+    let code = '';
+    document.onkeydown = function (e) {
+      let keycode = e.keyCode || e.which || e.charCode;
+      nextTime = new Date();
+      if (keycode === 13) {
+        if (lastTime && (nextTime - lastTime < 30)) {
+          // 扫码枪
+          // do something
+        } else {
+          // 键盘
+          // do something
+        }
+        code = '';
+        lastTime = null;
+        e.preventDefault();
+      } else {
+        if (!lastTime) {
+          code = String.fromCharCode(keycode);
+        } else {
+          if (nextTime - lastTime < 30) {
+            code += String.fromCharCode(keycode);
+          } else {
+            code = '';
+          }
+        }
+        lastTime = nextTime;
+      }
+      if (code.split('_').length === 2) {
+        _this.router.navigateByUrl('/enter-store')
+        _this.storage.set('pId', code.split('_')[0])
+        _this.storage.set('sscId', code.split('_')[1])
+      }
+      console.log(code)
+    }
+  }
+  checkLoginStatus() {
+    return this.userData.isLoggedIn().then(loggedIn => {
+      return this.updateLoggedInStatus(loggedIn);
+    });
+  }
+  updateLoggedInStatus(loggedIn: boolean) {
+    setTimeout(() => {
+      this.loggedIn = loggedIn;
+    }, 300);
+  }
+
+  listenForLoginEvents() {
+    this.events.subscribe('user:login', () => {
+      this.initWebSocket()
+      this.updateLoggedInStatus(true);
+    });
+    this.events.subscribe('user:logout', () => {
+      this.updateLoggedInStatus(false);
+    });
+  }
+  async logout() {
+    this.userData.logout()
+  }
+  initializeApp() {
+    this.platform.ready().then(() => {
+      this.statusBar.styleDefault();
+      this.splashScreen.hide();
+    });
+  }
+  //android通过返回按钮退出应用
+  lastTimeBackPress = 0;
+  timePeriodToExit = 2000;
+  backButtonEvent() {
+    this.platform.backButton.subscribe(() => {
+      if (this.router.url.indexOf('home') > -1 || this.router.url.indexOf('login') > -1 || this.router.url.indexOf('tab3') > -1) {
+        if (new Date().getTime() - this.lastTimeBackPress < this.timePeriodToExit) {
+          navigator['app'].exitApp(); //退出APP
+        } else {
+          this.presentAlertConfirm();
+          this.lastTimeBackPress = new Date().getTime();
+        }
+        // navigator['app'].exitApp(); //ionic4 退出APP的方法
+      }
+    })
+  }
+  async presentAlertConfirm() {
+    const alert = await this.alertController.create({
+      // header: 'Confirm!',
+      message: '您要退出APP吗?',
+      buttons: [
+        {
+          text: '取消',
+          role: 'cancel',
+          cssClass: 'secondary',
+          handler: (blah) => {
+          }
+        }, {
+          text: '退出',
+          handler: () => {
+            navigator['app'].exitApp();
+          }
+        }
+      ]
+    });
+
+    await alert.present();
+  }
+}

+ 63 - 0
src/app/app.module.ts

@@ -0,0 +1,63 @@
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+import { RouteReuseStrategy } from '@angular/router';
+
+import { IonicModule, IonicRouteStrategy } from '@ionic/angular';
+import { SplashScreen } from '@ionic-native/splash-screen/ngx';
+import { StatusBar } from '@ionic-native/status-bar/ngx';
+import { LoginGuardGuard } from '../guard/login-guard.guard';
+import { AppRoutingModule } from './app-routing.module';
+import { AppComponent } from './app.component';
+import { HttpModule } from '@angular/http';
+import { HttpClientModule } from '@angular/common/http';
+import { HTTP } from '@ionic-native/http/ngx';
+import { IonicStorageModule  } from '@ionic/storage'
+import { Camera } from '@ionic-native/camera/ngx';
+import { FullScreenImage } from '@ionic-native/full-screen-image/ngx';
+import { PhotoService } from '../services/photo.service';
+import { HttpserviceService} from '../services/httpservice.service';
+import { Keyboard } from '@ionic-native/keyboard/ngx';
+import { queryForm } from '../providers/query'
+import { AppVersion } from '@ionic-native/app-version/ngx'; 
+import { WebSocketService } from '../providers/WebSocketService';
+// import { BluetoothLE } from '@ionic-native/bluetooth-le/ngx'
+// import { BluetoothSerial } from '@ionic-native/bluetooth-serial/ngx';
+import { NativeService } from "../providers/native.service"
+import { Device } from '@ionic-native/device/ngx';
+import { LocalNotifications } from '@ionic-native/local-notifications/ngx';
+import { PopoverPage } from './qc-popover/qc-popover';
+import { File } from '@ionic-native/file/ngx';
+import { FileOpener } from '@ionic-native/file-opener/ngx';
+import { FileTransfer, FileTransferObject } from '@ionic-native/file-transfer/ngx';
+
+@NgModule({
+  declarations: [AppComponent,PopoverPage],
+  entryComponents: [PopoverPage],
+  imports: [BrowserModule,IonicStorageModule.forRoot(), IonicModule.forRoot(), AppRoutingModule, HttpModule, HttpClientModule],
+  providers: [
+    StatusBar,
+    SplashScreen,
+    LoginGuardGuard,
+    PhotoService,
+    Camera,
+    FullScreenImage,
+    Device,
+    File,
+    FileOpener,
+    FileTransfer,
+    FileTransferObject,
+    // BluetoothLE,
+    // BluetoothSerial,
+    Keyboard,
+    HttpserviceService,
+    LocalNotifications,
+    AppVersion,
+    NativeService,
+    WebSocketService,
+    queryForm,
+    { provide: RouteReuseStrategy, useClass: IonicRouteStrategy },
+    HTTP
+  ],
+  bootstrap: [AppComponent]
+})
+export class AppModule {}

+ 26 - 0
src/app/bluetooth/bluetooth.module.ts

@@ -0,0 +1,26 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormsModule } from '@angular/forms';
+import { Routes, RouterModule } from '@angular/router';
+
+import { IonicModule } from '@ionic/angular';
+
+import { BluetoothPage } from './bluetooth.page';
+
+const routes: Routes = [
+  {
+    path: '',
+    component: BluetoothPage
+  }
+];
+
+@NgModule({
+  imports: [
+    CommonModule,
+    FormsModule,
+    IonicModule,
+    RouterModule.forChild(routes)
+  ],
+  declarations: [BluetoothPage]
+})
+export class BluetoothPageModule {}

+ 79 - 0
src/app/bluetooth/bluetooth.page.html

@@ -0,0 +1,79 @@
+<ion-header>
+  <ion-toolbar>
+    <ion-buttons slot="start">
+      <ion-menu-button></ion-menu-button>
+    </ion-buttons>
+
+    <ion-title>蓝牙</ion-title>
+
+  </ion-toolbar>
+</ion-header>
+
+<ion-content>
+  <ion-list #scheduleList>
+    <ion-item-group>
+      <ion-item>
+        <ion-label>
+          蓝牙
+        </ion-label>
+        <ion-toggle slot="end" [(ngModel)]='blueStatus' (ionChange)='changeBlueStatus()'></ion-toggle>
+      </ion-item>
+      <ion-item-divider sticky *ngIf='blueStatus && connectList.length !== 0'>
+        <ion-label>
+          已连接的设备
+        </ion-label>
+      </ion-item-divider>  
+      <ion-item-sliding *ngFor='let l of connectList'>
+        <ion-item  (click)='cutLinkPrint()'>
+          <ion-label>
+            <span *ngIf='l.name'>{{l.name}}</span>
+            <span>(已连接)</span>
+          </ion-label>
+          <ion-note slot="end">
+            <ion-icon name="ios-alert-outline"></ion-icon>
+          </ion-note>
+        </ion-item>
+      </ion-item-sliding>
+      <ion-item-divider sticky>
+        <ion-label>
+          已配对设备
+        </ion-label>
+      </ion-item-divider>  
+      <ion-item-sliding *ngFor='let l of mateList'>
+        <ion-item button (click)='linkPrint(l)'>
+          <ion-label>
+            <span *ngIf='l.name'>{{l.name}}</span>
+            <span>{{l.address}}</span>
+          </ion-label>
+          <ion-note slot="end">
+            <ion-spinner icon="spiral" *ngIf='l.connectLoadingStatus'></ion-spinner>
+            <span *ngIf='l.connectStatus'>已连接</span>
+            <span *ngIf='!l.connectStatus'>未连接</span>
+          </ion-note>
+        </ion-item>
+      </ion-item-sliding>
+      <ion-item-divider sticky>
+        <ion-label>
+          搜索到的设备
+        </ion-label>
+        <ion-note color="primary" slot="end">
+          <span *ngIf='!blueStatus' (click)='getDiscoverList()'>开始搜索</span>
+          <span *ngIf='blueStatus' (click)='getDiscoverList()'>{{discoverWord}}</span>
+        </ion-note>
+      </ion-item-divider>
+      <ion-item-sliding (click)='linkPrint(device)' *ngFor="let device of discoverList">
+        <ion-item button>
+          <ion-label>
+            <h3>{{device.name}} {{device.id}}</h3>
+          </ion-label>
+          <ion-note slot="end" *ngIf='device.connectLoadingStatus'>
+            <ion-spinner icon="spiral"></ion-spinner>
+          </ion-note>
+        </ion-item>
+      </ion-item-sliding>
+    </ion-item-group>
+  </ion-list>
+</ion-content>
+<ion-footer>
+  <ion-button color="primary" type="submit" expand="block" (click)="write()">打印测试</ion-button>
+</ion-footer>

+ 19 - 0
src/app/bluetooth/bluetooth.page.scss

@@ -0,0 +1,19 @@
+$categories: (
+  ionic: var(--ion-color-primary),
+  angular: #ac282b,
+  communication: #8e8d93,
+  tooling: #fe4c52,
+  services: #fd8b2d,
+  design: #fed035,
+  workshop: #69bb7b,
+  food: #3bc7c4,
+  documentation: #b16be3,
+  navigation: #6600cc
+);
+
+@each $track, $value in map-remove($categories) {
+  ion-item-sliding[track='#{$track}'] ion-label {
+    border-left: 2px solid $value;
+    padding-left: 10px;
+  }
+}

+ 27 - 0
src/app/bluetooth/bluetooth.page.spec.ts

@@ -0,0 +1,27 @@
+import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { BluetoothPage } from './bluetooth.page';
+
+describe('BluetoothPage', () => {
+  let component: BluetoothPage;
+  let fixture: ComponentFixture<BluetoothPage>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ BluetoothPage ],
+      schemas: [CUSTOM_ELEMENTS_SCHEMA],
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(BluetoothPage);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

File diff suppressed because it is too large
+ 354 - 0
src/app/bluetooth/bluetooth.page.ts


+ 26 - 0
src/app/contract-detail/contract-detail.module.ts

@@ -0,0 +1,26 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormsModule } from '@angular/forms';
+import { Routes, RouterModule } from '@angular/router';
+
+import { IonicModule } from '@ionic/angular';
+
+import { ContractDetailPage } from './contract-detail.page';
+
+const routes: Routes = [
+  {
+    path: '',
+    component: ContractDetailPage
+  }
+];
+
+@NgModule({
+  imports: [
+    CommonModule,
+    FormsModule,
+    IonicModule,
+    RouterModule.forChild(routes)
+  ],
+  declarations: [ContractDetailPage]
+})
+export class ContractDetailPageModule {}

+ 83 - 0
src/app/contract-detail/contract-detail.page.html

@@ -0,0 +1,83 @@
+<ion-header>
+  <ion-toolbar>
+    <ion-buttons slot="start">
+      <ion-back-button [defaultHref]="defaultHref"></ion-back-button>
+    </ion-buttons>
+    <ion-title>采购合同详情</ion-title>
+    <ion-buttons slot="end">
+      <ion-button (click)="saveDetail()">
+        保存
+      </ion-button>
+    </ion-buttons>
+  </ion-toolbar>
+</ion-header>
+
+<ion-content>
+  <div class="detail-header">
+    <img src="../../assets/img/sg.png" alt="ionic logo">
+  </div>
+  <ion-item>
+    <ion-label>采购合同号:</ion-label>
+    <ion-input disabled>{{sscCode}}</ion-input>
+  </ion-item>
+<!--  <ion-item>-->
+<!--    <ion-label>下单员:</ion-label>-->
+<!--    <ion-input disabled>{{sscCreator}}</ion-input>-->
+<!--  </ion-item>-->
+<!--  <ion-item>-->
+<!--    <ion-label>合同日期:</ion-label>-->
+<!--    <ion-datetime disabled [(ngModel)]="scpModifiedtime"></ion-datetime>-->
+<!--  </ion-item>-->
+  <ion-list *ngFor="let contract of contractDetailList">
+    <ion-item-group>
+      <ion-item-divider sticky>
+        <ion-label>
+          详细信息
+        </ion-label>
+      </ion-item-divider>
+    </ion-item-group>
+    <ion-item lines="none">
+      <span>产品图片:</span>
+      <img slot="end" *ngIf="contract.imgsrc" [src]="contract.imgsrc" class="title-image"/>
+    </ion-item>
+
+    <ion-item>
+      <ion-label>
+        我司货号:
+      </ion-label>
+      <ion-input [(ngModel)]="contract.scpCode" disabled></ion-input>
+    </ion-item>
+    <ion-item>
+      <ion-label>
+        客户货号:
+      </ion-label>
+      <ion-input [(ngModel)]="contract.scpProductid" disabled></ion-input>
+    </ion-item>
+    <ion-item>
+      <ion-label>
+        中文品名:
+      </ion-label>
+      <ion-input [(ngModel)]="contract.scpCnname" disabled></ion-input>
+    </ion-item>
+    <!-- <ion-item>
+        <ion-label>
+          样品完成时间
+        </ion-label>
+        <ion-datetime [(ngModel)]="contract.sdpFinishcontract"></ion-datetime>
+      </ion-item> -->
+    <ion-item>
+      <ion-label>
+        QA日志:
+      </ion-label>
+      <ion-input [(ngModel)]="contract.qalog"></ion-input>
+      <ion-icon name="camera" slot="end" (click)="takePicture(contract)"></ion-icon>
+    </ion-item>
+    <ion-item>
+      <ion-label>QA日志图片:</ion-label>
+      <ion-thumbnail *ngIf="contract.imgUrl">
+        <ion-img [src]="contract.imgUrl"></ion-img>
+      </ion-thumbnail>
+      <ion-icon *ngIf="contract.imgUrl" name="close-circle-outline" (click)="deletePicture(contract)" slot="end"></ion-icon>
+    </ion-item>
+  </ion-list>
+</ion-content>

+ 6 - 0
src/app/contract-detail/contract-detail.page.scss

@@ -0,0 +1,6 @@
+.detail-header {
+    // background-color: var(--ion-color-dark);
+    padding: 20px;
+    width: 100%;
+    text-align: center;
+  }

+ 27 - 0
src/app/contract-detail/contract-detail.page.spec.ts

@@ -0,0 +1,27 @@
+import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { ContractDetailPage } from './contract-detail.page';
+
+describe('ContractDetailPage', () => {
+  let component: ContractDetailPage;
+  let fixture: ComponentFixture<ContractDetailPage>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ ContractDetailPage ],
+      schemas: [CUSTOM_ELEMENTS_SCHEMA],
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(ContractDetailPage);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 90 - 0
src/app/contract-detail/contract-detail.page.ts

@@ -0,0 +1,90 @@
+import { Component, OnInit } from '@angular/core';
+import { Storage } from '@ionic/storage'
+import { UserData } from '../../providers/user-data';
+import { Camera, CameraOptions } from '@ionic-native/camera/ngx';
+
+@Component({
+  selector: 'app-contract-detail',
+  templateUrl: './contract-detail.page.html',
+  styleUrls: ['./contract-detail.page.scss'],
+})
+export class ContractDetailPage implements OnInit {
+
+  defaultHref = '';
+  contractDetailList=[]
+  sscCode=''
+  sscCreator=''
+  scpModifiedtime=''
+  sscId=''
+  constructor(
+    private camera: Camera,
+    private storage: Storage,
+    public userData: UserData
+  ) { }
+
+  ngOnInit() {
+    this.storage.get('sscId').then(async (val) => {
+      if (val) {
+        this.sscId = val
+        let data = await this.userData.getContractDetail(val)
+        if (JSON.parse(data).data.length !== 0) {
+          this.sscCode = JSON.parse(data).data[0].scbCode
+          this.scpModifiedtime = JSON.parse(data).data[0].scpModifiedtime
+          this.contractDetailList = JSON.parse(data).data
+          for (let i of this.contractDetailList) {
+            // console.log(i)
+            let data = await this.userData.getQAlog(val, i.pid)
+            if (JSON.parse(data).data.length !== 0) {
+              i.qalog = JSON.parse(data).data[0].mark
+              i.imgUrl = JSON.parse(data).data[0].picture.split(",")[0]
+            }
+          }
+        }
+      }
+    });
+  }
+
+  ionViewDidEnter() {
+    this.defaultHref = `/contract-table`;
+  }
+
+  takePicture(contract) {
+    const options: CameraOptions = {
+      quality: 10,
+      destinationType: this.camera.DestinationType.DATA_URL,
+      encodingType: this.camera.EncodingType.JPEG,
+      mediaType: this.camera.MediaType.PICTURE
+    }
+
+    this.camera.getPicture(options).then((imageData) => {
+      contract.showPicture = true
+      contract.imgData = imageData
+      contract.imgUrl = 'data:image/jpeg;base64,' + imageData
+    }, (err) => {
+      // Handle error
+      console.log("Camera issue: " + err);
+    });
+  }
+
+  deletePicture(contract) {
+    contract.imgData = ''
+    contract.showPicture = false
+  }
+
+  async saveDetail() {
+    for(let i of this.contractDetailList) {
+      if(i.qalog && i.imgData) {
+        // let file = []
+        // file.push(i.imgData)
+        let form = {
+          files: i.imgData,
+          mark: i.qalog,
+          pId: i.pid,
+          sscId: this.sscId
+        }
+        await this.userData.contractQAlog(form)
+      }
+    }
+  }
+
+}

+ 26 - 0
src/app/contract-table/contract-table.module.ts

@@ -0,0 +1,26 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormsModule } from '@angular/forms';
+import { Routes, RouterModule } from '@angular/router';
+
+import { IonicModule } from '@ionic/angular';
+
+import { ContractTablePage } from './contract-table.page';
+
+const routes: Routes = [
+  {
+    path: '',
+    component: ContractTablePage
+  }
+];
+
+@NgModule({
+  imports: [
+    CommonModule,
+    FormsModule,
+    IonicModule,
+    RouterModule.forChild(routes)
+  ],
+  declarations: [ContractTablePage]
+})
+export class ContractTablePageModule {}

+ 50 - 0
src/app/contract-table/contract-table.page.html

@@ -0,0 +1,50 @@
+<ion-header>
+    <ion-toolbar>
+      <ion-buttons slot="start">
+        <ion-back-button [defaultHref]="defaultHref"></ion-back-button>
+      </ion-buttons>
+      <ion-title>采购合同列表</ion-title>
+    </ion-toolbar>
+  </ion-header>
+
+  <ion-content>
+    <ion-card *ngFor="let contract of contractList" (click)="getDetail(contract)">
+      <ion-card-content class="contract-content">
+        <div class="contract-title">
+          <ion-icon name="briefcase"></ion-icon>
+          <ion-label>供应商:</ion-label>
+          <ion-label>{{contract.sname}}</ion-label>
+        </div>
+<!--        <div class="contract-column">-->
+<!--          <ion-icon name="contract"></ion-icon>-->
+<!--          <ion-label>采购合同ID: </ion-label>-->
+<!--          <ion-label>{{contract.sscId}}</ion-label>-->
+<!--        </div>-->
+        <div class="contract-column">
+          <ion-icon name="folder"></ion-icon>
+          <ion-label>采购合同编号: </ion-label>
+          <ion-label>{{contract.sscCode}}</ion-label>
+        </div>
+        <!-- <div class="contract-column">
+          <ion-icon name="time"></ion-icon>
+          <ion-label>供应商编号:{{contract.sid}}</ion-label>
+          <ion-label></ion-label>
+        </div>
+        <div class="contract-column">
+          <ion-icon name="business"></ion-icon>
+          <ion-label>供应商名称: </ion-label>
+          <ion-label>{{contract.sdSelf}}</ion-label>
+        </div> -->
+        <div class="contract-column">
+          <ion-icon name="calendar"></ion-icon>
+          <ion-label>合同日期: </ion-label>
+          <ion-label>{{contract.sscContractdate}}</ion-label>
+        </div>
+        <div class="contract-column">
+          <ion-icon name="man"></ion-icon>
+          <ion-label>下单员: </ion-label>
+          <ion-label>{{contract.sscCreator}}</ion-label>
+        </div>
+      </ion-card-content>
+    </ion-card>
+  </ion-content>

+ 0 - 0
src/app/contract-table/contract-table.page.scss


+ 27 - 0
src/app/contract-table/contract-table.page.spec.ts

@@ -0,0 +1,27 @@
+import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { ContractTablePage } from './contract-table.page';
+
+describe('ContractTablePage', () => {
+  let component: ContractTablePage;
+  let fixture: ComponentFixture<ContractTablePage>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ ContractTablePage ],
+      schemas: [CUSTOM_ELEMENTS_SCHEMA],
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(ContractTablePage);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 32 - 0
src/app/contract-table/contract-table.page.ts

@@ -0,0 +1,32 @@
+import { Component, OnInit } from '@angular/core';
+import { Router } from '@angular/router';
+import { Storage } from '@ionic/storage'
+
+@Component({
+  selector: 'app-contract-table',
+  templateUrl: './contract-table.page.html',
+  styleUrls: ['./contract-table.page.scss'],
+})
+export class ContractTablePage implements OnInit {
+
+  defaultHref=""
+  contractList=[]
+  constructor(private router: Router, private storage: Storage) { }
+
+  ngOnInit() {
+    this.storage.get('contract-table-data').then((val) => {
+      if (val) {
+        this.contractList = JSON.parse(val).data
+      }
+    });
+  }
+  ionViewDidEnter() {
+    this.defaultHref = `/contract`;
+  }
+  getDetail(contract) {
+    this.storage.set('sscId',contract.sscId).then(()=>{
+      this.router.navigateByUrl('/contract-detail')
+    })
+    // this.storage.set('sdDocument',sample.sdDocument)
+  }
+}

+ 26 - 0
src/app/contract/contract.module.ts

@@ -0,0 +1,26 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormsModule } from '@angular/forms';
+import { Routes, RouterModule } from '@angular/router';
+
+import { IonicModule } from '@ionic/angular';
+
+import { ContractPage } from './contract.page';
+
+const routes: Routes = [
+  {
+    path: '',
+    component: ContractPage
+  }
+];
+
+@NgModule({
+  imports: [
+    CommonModule,
+    FormsModule,
+    IonicModule,
+    RouterModule.forChild(routes)
+  ],
+  declarations: [ContractPage]
+})
+export class ContractPageModule {}

+ 44 - 0
src/app/contract/contract.page.html

@@ -0,0 +1,44 @@
+<ion-header>
+  <ion-toolbar>
+    <ion-buttons slot="start">
+      <ion-menu-button></ion-menu-button>
+    </ion-buttons>
+    <ion-title>采购合同</ion-title>
+  </ion-toolbar>
+</ion-header>
+
+<ion-content>
+  <ion-list>
+    <ion-item>
+      <ion-label>采购合同号:</ion-label>
+      <ion-input [(ngModel)]="contractInfo.sscCode"></ion-input>
+    </ion-item>
+    <!-- <ion-item>
+      <ion-label>供应商名称:</ion-label>
+      <ion-datetime [(ngModel)]="contractInfo.sdCreateDateGt"></ion-datetime>
+    </ion-item>
+    <ion-item>
+      <ion-label>供应商编号:</ion-label>
+      <ion-input [(ngModel)]="contractInfo.sdStatus"></ion-input>
+    </ion-item> -->
+    <ion-item>
+      <ion-label>业务人员:</ion-label>
+      <ion-input [(ngModel)]="contractInfo.sscCreator"></ion-input>
+    </ion-item>
+    <!-- <ion-item>
+      <ion-label>状态:</ion-label>
+      <ion-input [(ngModel)]="contractInfo.sscState"></ion-input>
+    </ion-item> -->
+    <ion-item>
+      <ion-label>合同开始:</ion-label>
+      <ion-datetime [(ngModel)]="contractInfo.sscContractdateGt"></ion-datetime>
+    </ion-item>
+    <ion-item>
+      <ion-label>合同结束:</ion-label>
+      <ion-datetime [(ngModel)]="contractInfo.sscContractdateLt"></ion-datetime>
+    </ion-item>
+  </ion-list>
+  <div class="ion-padding">
+    <ion-button color="primary" expand="block" (click)="search()">查 询</ion-button>
+  </div>
+</ion-content>

+ 0 - 0
src/app/contract/contract.page.scss


+ 27 - 0
src/app/contract/contract.page.spec.ts

@@ -0,0 +1,27 @@
+import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { ContractPage } from './contract.page';
+
+describe('ContractPage', () => {
+  let component: ContractPage;
+  let fixture: ComponentFixture<ContractPage>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ ContractPage ],
+      schemas: [CUSTOM_ELEMENTS_SCHEMA],
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(ContractPage);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 70 - 0
src/app/contract/contract.page.ts

@@ -0,0 +1,70 @@
+import { Component, OnInit } from '@angular/core';
+import { UserData } from '../../providers/user-data';
+
+@Component({
+  selector: 'app-contract',
+  templateUrl: './contract.page.html',
+  styleUrls: ['./contract.page.scss'],
+})
+export class ContractPage implements OnInit {
+
+  contractInfo={
+    sscContractdateGt: '',
+    sscContractdateLt: '',
+    sscState: '',
+    sscCreator: '',
+    sscCode: ''
+  }
+  constructor(public userData: UserData) { }
+
+  ngOnInit() {
+  }
+  search() {
+    console.log(this.getSerchForm())
+    this.userData.getContractTableData(this.getSerchForm())
+  }
+  getSerchForm() {
+    let queryForm = {
+      query: {
+        bool: {
+          must: [],
+          must_not: [],
+          should: []
+        }
+      },
+      from: 0,
+      size: 10,
+      sort: [],
+      aggs: {}
+    };
+    if (this.contractInfo.sscCode) {
+      let prefix = {}
+      prefix['sscCode'] = this.contractInfo.sscCode
+      queryForm.query.bool.must.push({
+        prefix: prefix
+      })
+    }
+    if (this.contractInfo.sscContractdateGt || this.contractInfo.sscContractdateLt) {
+      let range = {
+        sscContractdate: {}
+      }
+      if (this.contractInfo.sscContractdateGt) {
+        range.sscContractdate['gt'] = new Date(this.contractInfo.sscContractdateGt).getTime()
+      }
+      if (this.contractInfo.sscContractdateLt) {
+        range.sscContractdate['lt'] = new Date(this.contractInfo.sscContractdateLt).getTime()
+      }
+      queryForm.query.bool.must.push({
+        range: range
+      })
+    }
+    if (this.contractInfo.sscCreator) {
+      let prefix = {}
+      prefix['sscCreator.keyword'] = this.contractInfo.sscCreator
+      queryForm.query.bool.must.push({
+        prefix: prefix
+      })
+    }
+    return queryForm
+  }
+}

+ 21 - 0
src/app/drawTab/drawTab.module.ts

@@ -0,0 +1,21 @@
+import { IonicModule } from '@ionic/angular';
+import { RouterModule } from '@angular/router';
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormsModule } from '@angular/forms';
+import { drawTabPage } from './drawTab.page';
+import { PhotoService } from '../../services/photo.service'
+
+@NgModule({
+  imports: [
+    IonicModule,
+    CommonModule,
+    FormsModule,
+    RouterModule.forChild([{ path: '', component: drawTabPage }])
+  ],
+  providers:[
+    PhotoService
+  ],
+  declarations: [drawTabPage]
+})
+export class drawTabPageModule {}

+ 33 - 0
src/app/drawTab/drawTab.page.html

@@ -0,0 +1,33 @@
+<ion-header (click)="doClick()">
+  <ion-toolbar>
+    <ion-buttons slot="start">
+      <ion-menu-button></ion-menu-button>
+    </ion-buttons>
+    <ion-title>
+      开单号
+    </ion-title>
+  </ion-toolbar>
+</ion-header>
+
+<ion-content (click)="doClick()">
+  <ion-item>
+    <ion-label>开单号:</ion-label>
+    <ion-input [(ngModel)]="ssfCode" #drawInput (ionChange)="codechange()" autofocus></ion-input>
+  </ion-item>
+  <ion-item>
+    <ion-label>当前单号:</ion-label>
+    <ion-input [(ngModel)]="currentCode" readonly></ion-input>
+  </ion-item>
+  <!-- <ion-grid>
+    <ion-row>
+      <ion-col size="6" *ngFor="let photo of photoService.photos">
+        <img [src]="photo.data" />
+      </ion-col>
+    </ion-row>
+  </ion-grid>
+  <ion-fab vertical="bottom" horizontal="center" slot="fixed">
+    <ion-fab-button (click)="photoService.takePicture()">
+      <ion-icon name="camera"></ion-icon>
+    </ion-fab-button> 
+  </ion-fab> -->
+</ion-content>

+ 4 - 0
src/app/drawTab/drawTab.page.scss

@@ -0,0 +1,4 @@
+.welcome-card ion-img {
+  max-height: 35vh;
+  overflow: hidden;
+}

+ 26 - 0
src/app/drawTab/drawTab.page.spec.ts

@@ -0,0 +1,26 @@
+import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { drawTabPage } from './drawTab.page';
+
+describe('drawTabPage', () => {
+  let component: drawTabPage;
+  let fixture: ComponentFixture<drawTabPage>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [drawTabPage],
+      schemas: [CUSTOM_ELEMENTS_SCHEMA],
+    }).compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(drawTabPage);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 94 - 0
src/app/drawTab/drawTab.page.ts

@@ -0,0 +1,94 @@
+import { Component, ViewChild } from '@angular/core';
+import { ToastController } from '@ionic/angular';
+import { HTTP } from '@ionic-native/http/ngx';
+import { from } from 'rxjs';
+import { finalize } from 'rxjs/operators';
+import { Storage } from '@ionic/storage'
+import { Camera, CameraOptions } from '@ionic-native/camera/ngx';
+import { PhotoService, Photo } from '../../services/photo.service';
+import { Keyboard } from '@ionic-native/keyboard/ngx';
+
+@Component({
+  selector: 'app-drawTab',
+  templateUrl: 'drawTab.page.html',
+  styleUrls: ['drawTab.page.scss']
+})
+export class drawTabPage {
+  // public photos: Photo[] = [];
+  private currentCode: string
+  private ssfCode: string
+  private access_token: string
+  constructor(private nativeHttp: HTTP,
+    // public photoService: PhotoService,
+    private storage: Storage,
+    private keyboard: Keyboard,
+    private camera: Camera,
+    private toastCtrl: ToastController) { }
+
+  @ViewChild('drawInput') drawInput;
+  ngOnInit() {
+    this.storage.get('access_token').then((val) => {
+      this.access_token = val
+    });
+  }
+  codechange() {
+    if (this.ssfCode) {
+      this.drawInput.value = ""
+      this.currentCode = this.ssfCode
+      this.getInfo()
+    }
+  }
+  ionViewDidEnter() {
+    this.keyboard.hide()  
+    this.inputFocus()
+    console.log('enter')
+  }
+  inputFocus() {
+    this.drawInput.setFocus();
+    this.keyboard.hide()
+  }
+  doClick() {
+    this.inputFocus()
+    this.keyboard.hide()
+    
+    console.log(this.keyboard)
+  }
+  // takePicture() {
+  //   const options: CameraOptions = {
+  //     quality: 100,
+  //     destinationType: this.camera.DestinationType.DATA_URL,
+  //     encodingType: this.camera.EncodingType.JPEG,
+  //     mediaType: this.camera.MediaType.PICTURE
+  //   }
+
+  //   this.camera.getPicture(options).then((imageData) => {
+  //     this.photos.unshift({
+  //       data: 'data:image/jpeg;base64,' + imageData
+  //     }); }, (err) => {
+  //     // Handle error
+  //     console.log("Camera issue: " + err);
+  //   });
+  // }
+  // 获取扫描信息
+  async getInfo() {
+    // let loading = await this.loadingCtrl.create();
+    let data = { ssfCode: this.currentCode }
+    this.nativeHttp.setDataSerializer('json');
+    let headers = { 'Authorization': `Bearer ${this.access_token}`, 'Content-Type': 'application/json;charset=UTF-8' }
+    // Returns a promise, need to convert with of() to Observable (if want)!
+    from(this.nativeHttp.post('http://192.168.20.32/production/sample/factory/',
+      data,
+      headers)).pipe(
+        finalize(() => { })
+      ).subscribe(data => {
+        this.storage.set('ssfId', JSON.parse(data.data).data.ssfId)
+      }, async err => {
+        let toast = await this.toastCtrl.create({
+          message: '获取数据失败',
+          duration: 1000,
+          position: 'top'
+        });
+        await toast.present();
+      });
+  }
+}

+ 26 - 0
src/app/enter-store/enter-store.module.ts

@@ -0,0 +1,26 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormsModule } from '@angular/forms';
+import { Routes, RouterModule } from '@angular/router';
+
+import { IonicModule } from '@ionic/angular';
+
+import { EnterStorePage } from './enter-store.page';
+
+const routes: Routes = [
+  {
+    path: '',
+    component: EnterStorePage
+  }
+];
+
+@NgModule({
+  imports: [
+    CommonModule,
+    FormsModule,
+    IonicModule,
+    RouterModule.forChild(routes)
+  ],
+  declarations: [EnterStorePage]
+})
+export class EnterStorePageModule {}

+ 177 - 0
src/app/enter-store/enter-store.page.html

@@ -0,0 +1,177 @@
+<ion-header>
+  <ion-toolbar>
+    <ion-buttons slot="start">
+      <ion-menu-button></ion-menu-button>
+    </ion-buttons>
+    <ion-title>入库单</ion-title>
+    <ion-buttons slot="end">
+      <ion-button [disabled]="storeList.length===0" (click)="saveStore()">
+        保存
+      </ion-button>
+    </ion-buttons>
+  </ion-toolbar>
+</ion-header>
+
+<ion-content>
+  <ion-item>
+    <ion-label>条形码编号:</ion-label>
+    <ion-input #scanInput clear-on-edit (ionChange)="getStoreDetail()" [(ngModel)]="scanCode"></ion-input>
+  </ion-item>
+  <form #storeForm="ngForm" novalidate>
+    <ion-list *ngFor="let store of storeDetailList">
+      <ion-item-group>
+        <ion-item-divider sticky>
+          <ion-label>
+            详细信息
+          </ion-label>
+        </ion-item-divider>
+      </ion-item-group>
+      <ion-item>
+        <ion-label>
+          外销合同编号:
+        </ion-label>
+        <ion-input [(ngModel)]="store.scpCode" name="scanCode" #scpCode="ngModel" disabled></ion-input>
+      </ion-item>
+
+      <ion-item>
+        <ion-label>
+          采购合同编号:
+        </ion-label>
+        <ion-input [(ngModel)]="store.scpCustomercode" name="scpCustomercode" #scpCustomercode="ngModel" disabled>
+        </ion-input>
+      </ion-item>
+
+      <ion-item>
+        <ion-label>
+          我司货号:
+        </ion-label>
+        <ion-input [(ngModel)]="store.scpCode" name="scpCode" #scpCode="ngModel" disabled>
+        </ion-input>
+      </ion-item>
+      <ion-item>
+        <ion-label>
+          中文品名:
+        </ion-label>
+        <ion-input [(ngModel)]="store.scpCnname" name="scpCnname" #scpCnname="ngModel" disabled>
+        </ion-input>
+      </ion-item>
+      <ion-item>
+        <ion-label>
+          合同数量:
+        </ion-label>
+        <ion-input [(ngModel)]="store.scpAmount" name="scpAmount" #scpAmount="ngModel" disabled>
+        </ion-input>
+      </ion-item>
+      <ion-item>
+        <ion-label>
+          合同箱数:
+        </ion-label>
+        <ion-input [(ngModel)]="store.contractBoxs" name="contractBoxs" #contractBoxs="ngModel" disabled>
+        </ion-input>
+      </ion-item>
+      <ion-item>
+        <ion-label>
+          在库数量:
+        </ion-label>
+        <ion-input [(ngModel)]="store.count" name="count" #count="ngModel" disabled>
+        </ion-input>
+      </ion-item>
+      <ion-item>
+        <ion-label>
+          在库箱数:
+        </ion-label>
+        <ion-input [(ngModel)]="store.storeBoxs" name="storeBoxs" #storeBoxs="ngModel" disabled>
+        </ion-input>
+      </ion-item>
+
+      <ion-item>
+        <ion-label>
+          外箱长度:
+        </ion-label>
+        <ion-input [(ngModel)]="store.outboxlength" name="outboxlength" #outboxlength="ngModel" required></ion-input>
+      </ion-item>
+      <ion-text color="danger">
+        <p [hidden]="!(!store.outboxlength&&clicked)" class="ion-padding-start">
+          请输入外箱长度
+        </p>
+      </ion-text>
+
+      <ion-item>
+        <ion-label>
+          外箱宽度:
+        </ion-label>
+        <ion-input [(ngModel)]="store.outboxwidth" name="outboxwidth" #outboxlength="ngModel" required></ion-input>
+      </ion-item>
+      <ion-text color="danger">
+        <p [hidden]="!(!store.outboxwidth&&clicked)" class="ion-padding-start">
+          请输入外箱宽度
+        </p>
+      </ion-text>
+
+      <ion-item>
+        <ion-label>
+          外箱高度:
+        </ion-label>
+        <ion-input [(ngModel)]="store.outboxheigt" name="outboxheigt" #outboxlength="ngModel" required></ion-input>
+      </ion-item>
+      <ion-text color="danger">
+        <p [hidden]="!(!store.outboxheigt&&clicked)" class="ion-padding-start">
+          请输入外箱高度
+        </p>
+      </ion-text>
+
+      <ion-item>
+        <ion-label>
+          入库箱数:
+        </ion-label>
+        <ion-input [(ngModel)]="store.enterBoxs" name="enterBoxs" #outboxlength="ngModel" required></ion-input>
+      </ion-item>
+      <ion-text color="danger">
+        <p [hidden]="!(!store.enterBoxs&&clicked)" class="ion-padding-start">
+          请输入入库箱数
+        </p>
+      </ion-text>
+
+      <ion-item>
+        <ion-label>
+          仓位编号:
+        </ion-label>
+        <ion-input [(ngModel)]="store.storelocation" name="storelocation" #outboxlength="ngModel" required></ion-input>
+      </ion-item>
+      <ion-text color="danger">
+        <p [hidden]="!(!store.storelocation&&clicked)" class="ion-padding-start">
+          请输入仓位编号
+        </p>
+      </ion-text>
+
+      <ion-item>
+        <ion-label>
+          毛重:
+        </ion-label>
+        <ion-input [(ngModel)]="store.grossweight" name="grossweight" #outboxlength="ngModel" required></ion-input>
+      </ion-item>
+      <ion-text color="danger">
+        <p [hidden]="!(!store.grossweight&&clicked)" class="ion-padding-start">
+          请输入毛重
+        </p>
+      </ion-text>
+    </ion-list>
+    <div class="ion-padding">
+      <ion-button color="primary" type="submit" expand="block" (click)="saveRecord(storeForm)"
+        [disabled]="storeDetailList.length===0">记 录</ion-button>
+    </div>
+    <ion-list>
+      <ion-item-group>
+        <ion-item-divider sticky>
+          <ion-label>
+            已扫描条形码编号
+          </ion-label>
+        </ion-item-divider>
+      </ion-item-group>
+      <ion-item *ngFor="let item of storeList index as i">
+        <ion-label color="primary" (click)="getStoreDetail(item)">{{item.scpCode}}({{item.scanCode}})</ion-label>
+        <ion-icon name="trash" (click)="deleteStore(item, i)"></ion-icon>
+      </ion-item>
+    </ion-list>
+  </form>
+</ion-content>

+ 0 - 0
src/app/enter-store/enter-store.page.scss


+ 27 - 0
src/app/enter-store/enter-store.page.spec.ts

@@ -0,0 +1,27 @@
+import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { EnterStorePage } from './enter-store.page';
+
+describe('EnterStorePage', () => {
+  let component: EnterStorePage;
+  let fixture: ComponentFixture<EnterStorePage>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ EnterStorePage ],
+      schemas: [CUSTOM_ELEMENTS_SCHEMA],
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(EnterStorePage);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 135 - 0
src/app/enter-store/enter-store.page.ts

@@ -0,0 +1,135 @@
+import { Component, OnInit, ViewChild } from '@angular/core';
+import { AlertController } from '@ionic/angular';
+import { Storage } from '@ionic/storage'
+import { UserData } from '../../providers/user-data';
+import { NgForm } from '@angular/forms';
+import { Keyboard } from '@ionic-native/keyboard/ngx';
+
+@Component({
+  selector: 'app-enter-store',
+  templateUrl: './enter-store.page.html',
+  styleUrls: ['./enter-store.page.scss'],
+})
+export class EnterStorePage implements OnInit {
+  clicked = false
+  storeDetailList = []
+  storeList = []
+  scpCodes = []
+  scanCode: string
+  pId: number
+  sscId: number
+  entergoodsCode: any
+  constructor(
+    private storage: Storage,
+    public userData: UserData,
+    private keyboard: Keyboard,
+    private alertController: AlertController, ) { }
+
+  @ViewChild('scanInput') scanInput;
+  ngOnInit() {
+    // this.getStoreDetail()
+    // console.log('enter-store')
+  }
+
+  // 进入页面
+  ionViewDidEnter() {
+    this.initialData()
+  }
+
+  initialData() {
+    this.storeDetailList = []
+    this.clicked = false
+    this.scanCode = ''
+    this.scanInput.setFocus();
+  }
+  
+  // async getId() {
+  //   await this.storage.get('pId').then((val) => {
+  //     this.pId = val
+  //     this.entergoodsCode = val
+  //   })
+  //   await this.storage.get('sscId').then((val) => {
+  //     this.sscId = val
+  //   })
+  // }
+  // 获取入库单详情
+  async getStoreDetail(item) {
+    // console.log(this.scanCode)
+    this.keyboard.hide()
+    if (item) {
+      this.scanCode = item.scanCode
+      this.storeDetailList = item
+    } else {
+      if (this.scanCode.split('_').length === 2) {
+        let filterData = []
+        filterData = this.storeList.filter(item => { return item.sscId == this.scanCode.split('_')[0] && item.pid == this.scanCode.split('_')[1] })
+        if (filterData.length !== 0) {
+          this.storeDetailList = filterData
+        } else {
+          let data = await this.userData.getStoreDetail(Number(this.scanCode.split('_')[0]), Number(this.scanCode.split('_')[1]))
+          this.storeDetailList = new Array(JSON.parse(data).data)
+        }
+      }
+      // console.log(this.storeDetailList)
+    }
+    // await this.getId()
+    // if(this.pId && this.sscId) {
+    //   this.storeDetailList = await this.userData.getStoreDetail(this.pId,this.sscId)
+    // }
+  }
+  // 记录数据
+  async saveRecord(form: NgForm) {
+    let _this = this
+    this.clicked = true
+    if (form.valid) {
+      // 是否已扫描记录过该数据
+      let filterData = []
+      filterData = this.storeList.filter(item => {
+        return item.sscId == this.storeDetailList[0].sscId && item.pid == this.storeDetailList[0].pid
+      })
+      // 有则更新
+      if (filterData.length !== 0) {
+        filterData = this.storeDetailList
+        // 无则加上  
+      } else {
+        this.storeList = this.storeList.concat(this.storeDetailList)
+      }
+      // 显示记录中的外销合同号
+      // this.scpCodes = []
+      for (let i of this.storeList) {
+        i.enterCount = Number(i.enterBoxs) * Number(i.scpOutrate)
+        i.amount = i.enterCount
+        i.scanCode = this.scanCode
+        // this.scpCodes.push(i.scpCode)
+      }
+      this.initialData()
+      // const alert = await this.alertController.create({
+      //   // header: 'Confirm!',
+      //   message: `记录成功,当前记录外销合同${scpCodes}`,
+      //   buttons: [
+      //     {
+      //       text: '确定',
+      //       role: 'cancel',
+      //       cssClass: 'secondary',
+      //       handler: (blah) => {
+      //         _this.clicked = false
+      //         _this.scanCode = ''
+      //         _this.scanInput.setFocus();
+      //       }
+      //     }
+      //   ]
+      // });
+      // await alert.present();
+    }
+  }
+
+  deleteStore(store, index) {
+    this.storeList.splice(index)
+  }
+
+  // 保存并生成货号
+  async saveStore() {
+    await this.userData.saveStoreDetail(this.storeList)
+    // this.scanInput.setFocus();
+  }
+}

+ 26 - 0
src/app/infoTab/infoTab.module.ts

@@ -0,0 +1,26 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormsModule } from '@angular/forms';
+import { Routes, RouterModule } from '@angular/router';
+
+import { IonicModule } from '@ionic/angular';
+
+import { infoTabPage } from './infoTab.page';
+
+const routes: Routes = [
+  {
+    path: '',
+    component: infoTabPage
+  }
+];
+
+@NgModule({
+  imports: [
+    CommonModule,
+    FormsModule,
+    IonicModule,
+    RouterModule.forChild(routes)
+  ],
+  declarations: [infoTabPage]
+})
+export class infoTabPageModule {}

+ 45 - 0
src/app/infoTab/infoTab.page.html

@@ -0,0 +1,45 @@
+<ion-header (click)="doClick()">
+  <ion-toolbar>
+    <ion-buttons slot="start">
+      <ion-menu-button></ion-menu-button>
+    </ion-buttons>
+    <ion-title>
+      样品扫描
+    </ion-title>
+  </ion-toolbar>
+</ion-header>
+
+<ion-content (click)="doClick()">
+
+  <ion-item>
+    <ion-label>货号:</ion-label>
+    <ion-input [(ngModel)]="pCode" #infoInput clear-input clear-on-edit (ionChange)="pcodechange()" autofocus>
+    </ion-input>
+  </ion-item>
+
+  <ion-item>
+    <ion-label>当前货号:</ion-label>
+    <ion-input [(ngModel)]="currentpCode" readonly></ion-input>
+  </ion-item>
+
+  <ion-item>
+    <ion-label>优胜厂:</ion-label>
+    <ion-input readonly [(ngModel)]="supplierName"></ion-input>
+  </ion-item>
+
+  <ion-item>
+    <ion-label>外发工厂:</ion-label>
+    <ion-input readonly [(ngModel)]="outSendFactoryName"></ion-input>
+  </ion-item>
+
+  <ion-item>
+    <ion-thumbnail slot="end">
+      <ion-img [src]="imgSrc"></ion-img>
+    </ion-thumbnail>
+    <ion-label>图片:</ion-label>
+  </ion-item>
+
+  <div class="ion-padding">
+    <ion-button expand="block" color="primary" (click)="save()">保存</ion-button>
+  </div>
+</ion-content>

+ 18 - 0
src/app/infoTab/infoTab.page.router.module.ts

@@ -0,0 +1,18 @@
+import { NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+import { infoTabPage } from './infoTab.page';
+
+const routes: Routes = [
+  {
+    path: 'infoTab',
+    component: infoTabPage,
+  }
+];
+
+@NgModule({
+  imports: [
+    RouterModule.forChild(routes)
+  ],
+  exports: [RouterModule]
+})
+export class LoginPageRoutingModule {}

+ 12 - 0
src/app/infoTab/infoTab.page.scss

@@ -0,0 +1,12 @@
+.item ion-thumbnail {
+    min-width: 5vh;    
+    min-height: 5vh;
+    img {
+        max-width: 5vh;    
+        min-width: 5vh;
+    }
+}
+.item-input.sc-ion-label-ios-h, .item-input .sc-ion-label-ios-h {
+    width: 20vw;
+    opacity: 1;
+}

+ 27 - 0
src/app/infoTab/infoTab.page.spec.ts

@@ -0,0 +1,27 @@
+import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { infoTabPage } from './infoTab.page';
+
+describe('infoTabPage', () => {
+  let component: infoTabPage;
+  let fixture: ComponentFixture<infoTabPage>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ infoTabPage ],
+      schemas: [CUSTOM_ELEMENTS_SCHEMA],
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(infoTabPage);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 108 - 0
src/app/infoTab/infoTab.page.ts

@@ -0,0 +1,108 @@
+import { Component, OnInit, ViewChild } from '@angular/core';
+import { from } from 'rxjs';
+import { HTTP } from '@ionic-native/http/ngx';
+import { LoadingController, ToastController } from '@ionic/angular';
+import { finalize } from 'rxjs/operators';
+import { Keyboard } from '@ionic-native/keyboard/ngx';
+import { Storage } from '@ionic/storage'
+
+@Component({
+  selector: 'app-infoTab',
+  templateUrl: './infoTab.page.html',
+  styleUrls: ['./infoTab.page.scss'],
+})
+export class infoTabPage implements OnInit {
+  private ssfCode: string
+  private pCode: string
+  private currentpCode: string
+  private supplierName: string
+  private outSendFactoryName: string
+  private imgSrc: string
+  private ssfId: any
+  private access_token: string
+  constructor(private nativeHttp: HTTP,
+    private loadingCtrl: LoadingController,
+    private storage: Storage,
+    private keyboard: Keyboard,
+    private toastCtrl: ToastController) { }
+
+  @ViewChild('infoInput') infoInput;
+
+  ngOnInit() {
+    this.storage.get('access_token').then((val) => {
+      this.access_token = val
+    });
+  }
+  ionViewDidEnter() {
+    this.inputFocus()
+    console.log('enter')
+  }
+  pcodechange() {
+    if (this.pCode) {
+      this.infoInput.value = ''
+      this.currentpCode = this.pCode
+      this.getPcodeInfo()
+    }
+  }
+  inputFocus() {
+    this.infoInput.setFocus();
+    this.keyboard.hide()
+  }
+  doClick() {
+    this.inputFocus()
+    console.log('click info')
+  }
+  // 扫描货号获取详细信息
+  async getPcodeInfo() {
+    this.storage.get('ssfId').then((val) => {
+      this.ssfId = val
+    });
+    let headers = { 'Authorization': `Bearer ${this.access_token}`, 'Content-Type': 'application/json;charset=UTF-8' }
+    // Returns a promise, need to convert with of() to Observable (if want)!
+    from(this.nativeHttp.get('http://192.168.20.32/production/sample/factory/pCode',
+      { pCode: this.currentpCode },
+      headers)).pipe(
+        finalize(() => { })
+      ).subscribe(data => {
+        this.supplierName = (JSON.parse(data.data).data).supplierName
+        this.outSendFactoryName = (JSON.parse(data.data).data).outSendFactoryName
+        if ((JSON.parse(data.data).data).pictures.length !== 0) {
+          this.imgSrc = (JSON.parse(data.data).data).pictures[0].smallPicture
+        }
+      }, async err => {
+        let toast = await this.toastCtrl.create({
+          message: '获取数据失败',
+          duration: 1000,
+          position: 'top'
+        });
+        await toast.present();
+      });
+  }
+  async save() {
+    this.nativeHttp.setDataSerializer('json');
+    let data = { ssfCode: this.currentpCode, ssfId: this.ssfId }
+    let headers = { 'Authorization': `Bearer ${this.access_token}`, 'Content-Type': 'application/json;charset=UTF-8' }
+    // Returns a promise, need to convert with of() to Observable (if want)!
+    from(this.nativeHttp.post('http://192.168.20.32/production/sample/factory/details/',
+      data,
+      headers)).pipe(
+        finalize(() => { })
+      ).subscribe(async data => {
+        if (JSON.parse(data.data).msg === 'success') {
+          let toast = await this.toastCtrl.create({
+            message: '保存成功',
+            position: 'top',
+            duration: 1000
+          });
+          toast.present()
+        }
+      }, async err => {
+        let toast = await this.toastCtrl.create({
+          message: '保存失败',
+          duration: 1000,
+          position: 'top'
+        });
+        await toast.present();
+      });
+  }
+}

+ 56 - 0
src/app/login/login.page.html

@@ -0,0 +1,56 @@
+<!--
+  Generated template for the LoginPage page.
+
+  See http://ionicframework.com/docs/components/#navigation for more info on
+  Ionic pages and navigation.
+-->
+<ion-header>
+  <ion-toolbar class="header">
+    <ion-buttons slot="start">
+      <ion-menu-button></ion-menu-button>
+    </ion-buttons>
+    <ion-title>用户登录</ion-title>
+    <!-- <ion-buttons>
+      <ion-button ion-button>
+        <span color="primary" showWhen="ios">取消</span>
+        <ion-icon name="md-close" showWhen="android"></ion-icon> 
+      </ion-button>
+    </ion-buttons>-->
+  </ion-toolbar>
+</ion-header>
+
+<ion-content>
+  <div class="login-logo">
+    <img src="assets/img/sg.png" alt="Ionic logo">
+  </div>
+  <form #loginForm="ngForm" novalidate>
+    <ion-list>
+      <ion-item>
+        <ion-label position="stacked" class="account">账号</ion-label>
+        <ion-input clearInput type="text" [(ngModel)]="loginInfo.account" name="account" #account="ngModel" required>
+        </ion-input>
+      </ion-item>
+      <ion-text color="danger">
+        <p [hidden]="account.valid || submitted == false" class="ion-padding-start">
+          请输入用户名
+        </p>
+      </ion-text>
+      <ion-item>
+        <ion-label position="stacked" class="account">密码</ion-label>
+        <ion-input clearInput type="password" name="password" #password="ngModel" [(ngModel)]="loginInfo.password"
+          required></ion-input>
+      </ion-item>
+      <ion-text color="danger">
+        <p [hidden]="password.valid || submitted == false" class="ion-padding-start">
+          请输入密码
+        </p>
+      </ion-text>
+    </ion-list>
+    <div class="ion-padding">
+      <ion-button color="primary" type="submit" expand="block" (click)="login(loginForm)">登 录</ion-button>
+    </div>
+    <!-- <div class="ion-padding" text-center>
+      <ion-button ion-button color="primary" fill="outline" (click)="pushRegisterPage()">没有账号?注册</ion-button>
+    </div> -->
+  </form>
+</ion-content>

+ 23 - 0
src/app/login/login.page.module.ts

@@ -0,0 +1,23 @@
+import { NgModule } from '@angular/core';
+import { IonicModule } from '@ionic/angular';
+import { CommonModule } from '@angular/common';
+import { FormsModule } from '@angular/forms';
+import { LoginPageRoutingModule } from './login.page.router.module';
+import { LoginPage } from './login.page';
+import { IonicStorageModule } from '@ionic/storage';
+import { ApiProvider } from '../../providers/api/api'
+
+@NgModule({
+  declarations: [
+    LoginPage,
+  ],
+  imports: [
+    IonicModule,
+    CommonModule,
+    FormsModule,
+    LoginPageRoutingModule,
+    IonicStorageModule.forRoot()
+  ],
+  providers: [ApiProvider]
+})
+export class LoginPageModule {}

+ 23 - 0
src/app/login/login.page.router.module.ts

@@ -0,0 +1,23 @@
+import { NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+import { LoginPage } from './login.page';
+
+const routes: Routes = [
+  {
+    path: 'login',
+    component: LoginPage,
+  },
+  {
+    path: '',
+    redirectTo: '/login',
+    pathMatch: 'full'
+  }
+];
+
+@NgModule({
+  imports: [
+    RouterModule.forChild(routes)
+  ],
+  exports: [RouterModule]
+})
+export class LoginPageRoutingModule {}

+ 11 - 0
src/app/login/login.page.scss

@@ -0,0 +1,11 @@
+.header {
+  background-color: #f8f8f8;
+}
+.login-logo {
+  padding: 20px 0;
+  text-align: center;
+}
+.account {
+  color: #3880ff;
+  font-size: 16px;
+}

+ 88 - 0
src/app/login/login.page.ts

@@ -0,0 +1,88 @@
+import { Component } from '@angular/core';
+import { ModalController, Platform } from '@ionic/angular';
+import { BaseUI } from '../../common/baseui'
+import { NgForm } from '@angular/forms';
+// import { ApiProvider } from '../../providers/api/api'
+import { Storage } from '@ionic/storage'
+import { Injectable } from '@angular/core';
+
+import { HttpClient } from '@angular/common/http';
+
+import * as CryptoJS from "crypto-js"
+import { UserData } from '../../providers/user-data';
+// import {Directive} from '@angular/core';
+// import { RegisterPage } from '../register/register'
+
+/**
+ * Generated class for the LoginPage page.
+ *
+ * See https://ionicframework.com/docs/components/#navigation for more info on
+ * Ionic pages and navigation.
+ */
+
+@Injectable()
+
+// @Directive({
+//   selector: '[clickOutside]'
+// })
+
+@Component({
+  selector: 'page-login',
+  templateUrl: 'login.page.html',
+  styleUrls: ['login.page.scss']
+})
+export class LoginPage extends BaseUI {
+  submitted = false;
+  constructor(private http: HttpClient,
+    private storage: Storage,
+    private plt: Platform,
+    public userData: UserData) {
+    super()
+  }
+  loginInfo = { account: '', password: '' };
+  errorMessage: any;
+  async login(form: NgForm) {
+    const user = this.encryption({
+      data: this.loginInfo,
+      key: 'pigxpigxpigxpigx',
+      param: ['password']
+    })
+    this.submitted = true
+    if (form.valid) {
+      this.userData.login(user.account, user.password);
+    }
+  }
+  /**
+ *加密处理
+ */
+  encryption = (params) => {
+    let {
+      data,
+      type,
+      param,
+      key
+    } = params
+    const result = JSON.parse(JSON.stringify(data))
+    if (type === 'Base64') {
+      param.forEach(ele => {
+        result[ele] = btoa(result[ele])
+      })
+    } else {
+      param.forEach(ele => {
+        var data = result[ele]
+        key = CryptoJS.enc.Latin1.parse(key)
+        var iv = key
+        // 加密
+        var encrypted = CryptoJS.AES.encrypt(
+          data,
+          key, {
+            iv: iv,
+            mode: CryptoJS.mode.CBC,
+            padding: CryptoJS.pad.ZeroPadding
+          })
+        result[ele] = encrypted.toString()
+      })
+    }
+    return result
+  }
+}

+ 29 - 0
src/app/qc-popover/qc-popover.ts

@@ -0,0 +1,29 @@
+import { Component } from '@angular/core';
+
+import { PopoverController } from '@ionic/angular';
+
+@Component({
+  template: `
+    <ion-list>
+      <ion-item button (click)="recordQC()">
+        <ion-label>记录</ion-label>
+      </ion-item>
+      <ion-item button (click)="generateQC()">
+        <ion-label>生成</ion-label>
+      </ion-item>
+    </ion-list>
+  `
+})
+export class PopoverPage {
+  constructor(public popoverCtrl: PopoverController) {}
+
+  support() {
+    // this.app.getRootNavs()[0].push('/support');
+    this.popoverCtrl.dismiss();
+  }
+
+  close(url: string) {
+    window.open(url, '_blank');
+    this.popoverCtrl.dismiss();
+  }
+}

+ 30 - 0
src/app/sample-detail/sample-detail.module.ts

@@ -0,0 +1,30 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormsModule } from '@angular/forms';
+import { Routes, RouterModule } from '@angular/router';
+
+import { IonicModule } from '@ionic/angular';
+
+import { SampleDetailPage } from './sample-detail.page';
+import { PhotoService } from '../../services/photo.service'
+
+const routes: Routes = [
+  {
+    path: '',
+    component: SampleDetailPage
+  }
+];
+
+@NgModule({
+  imports: [
+    CommonModule,
+    FormsModule,
+    IonicModule,
+    RouterModule.forChild(routes)
+  ],
+  providers:[
+    PhotoService
+  ],
+  declarations: [SampleDetailPage]
+})
+export class SampleDetailPageModule {}

+ 110 - 0
src/app/sample-detail/sample-detail.page.html

@@ -0,0 +1,110 @@
+<ion-header>
+  <ion-toolbar>
+    <ion-buttons slot="start">
+      <ion-back-button [defaultHref]="defaultHref"></ion-back-button>
+    </ion-buttons>
+    <ion-title>样品单详情</ion-title>
+    <ion-buttons slot="end">
+      <ion-button (click)="saveDetail()">
+        保存
+      </ion-button>
+    </ion-buttons>
+  </ion-toolbar>
+</ion-header>
+
+<ion-content>
+  <div class="detail-header">
+    <img src="../../assets/img/sg.png" alt="ionic logo">
+  </div>
+  <ion-item>
+    <ion-label>样品单号:</ion-label>
+    <ion-input disabled>{{sdDocument}}</ion-input>
+  </ion-item>
+  <ion-item>
+    <ion-label>下单人:</ion-label>
+    <ion-input sdMan>{{sdMan}}</ion-input>
+  </ion-item>
+<!--  <ion-item>-->
+<!--    <ion-label>交样时间:</ion-label>-->
+<!--    <ion-datetime disabled [(ngModel)]="sdpModifydate"></ion-datetime>-->
+<!--  </ion-item>-->
+  <ion-list *ngFor="let sample of sampleDetailList">
+    <!-- <ion-item-group>
+      <ion-item-divider sticky>
+        <ion-label>
+          主要信息
+        </ion-label>
+      </ion-item-divider>
+    </ion-item-group> -->
+    <ion-item-group>
+      <ion-item-divider sticky>
+        <ion-label>
+          样品单
+        </ion-label>
+      </ion-item-divider>
+    </ion-item-group>
+
+    <ion-item lines="none">
+      <span>产品图片:</span>
+      <img slot="end" [src]="sample.imgsrc" class="title-image"/>
+    </ion-item>
+
+    <ion-item>
+      <ion-label>
+        我司货号:
+      </ion-label>
+      <ion-input [(ngModel)]="sample.sdpCode" disabled></ion-input>
+    </ion-item>
+    <ion-item>
+      <ion-label>
+        客户货号:
+      </ion-label>
+      <ion-input [(ngModel)]="sample.sdpCustomercode" disabled></ion-input>
+    </ion-item>
+    <ion-item>
+      <ion-label>
+        中文品名:
+      </ion-label>
+      <ion-input [(ngModel)]="sample.sdpCname" disabled></ion-input>
+    </ion-item>
+    <!-- <ion-item>
+      <ion-label>
+        样品完成时间:
+      </ion-label>
+      <ion-datetime [(ngModel)]="sample.sdpFinishSample"></ion-datetime>
+    </ion-item> -->
+    <ion-item>
+      <ion-label>
+        QA日志:
+      </ion-label>
+      <ion-input [(ngModel)]="sample.qalog"></ion-input>
+      <ion-icon name="camera" slot="end" (click)="takePicture(sample)"></ion-icon>
+      <!-- <ion-col size="6" *ngFor="let photo of photos"> -->
+      <!-- <img [src]="photo.data" /> -->
+      <!-- </ion-col> -->
+    </ion-item>
+    <ion-item>
+      <ion-label>QA日志图片:</ion-label>
+      <!-- <ng-container *ngFor="let photo of sample.imgList index as i"> -->
+      <ion-thumbnail *ngIf="sample.imgUrl">
+        <ion-img [src]="sample.imgUrl"></ion-img>
+      </ion-thumbnail>
+      <ion-icon *ngIf="sample.imgUrl" name="close-circle-outline" (click)="deletePicture(sample)" slot="end"></ion-icon>
+    <!-- </ng-container> -->
+      <!-- <ion-label>{{sample.imgUrl}}</ion-label> -->
+      
+    </ion-item>
+    <!-- <ion-grid>
+      <ion-row>
+        <ion-col size="6" *ngFor="let photo of photos">
+          <img [src]="photo.data" />
+        </ion-col>
+      </ion-row>
+    </ion-grid> -->
+  </ion-list>
+  <!-- <ion-fab vertical="bottom" horizontal="center" slot="fixed">
+    <ion-fab-button (click)="takePicture()">
+      <ion-icon name="camera"></ion-icon>
+    </ion-fab-button>
+  </ion-fab> -->
+</ion-content>

+ 30 - 0
src/app/sample-detail/sample-detail.page.scss

@@ -0,0 +1,30 @@
+.detail-header {
+    // background-color: var(--ion-color-dark);
+    padding: 20px;
+    width: 100%;
+    text-align: center;
+  }
+  $categories: (
+  ionic: var(--ion-color-primary),
+  angular: #ac282b,
+  communication: #8e8d93,
+  tooling: #fe4c52,
+  services: #fd8b2d,
+  design: #fed035,
+  workshop: #69bb7b,
+  food: #3bc7c4,
+  documentation: #b16be3,
+  navigation: #6600cc
+);
+
+.title-image {
+  width: auto;
+  height: 60px;
+}
+
+@each $track, $value in map-remove($categories) {
+  ion-item-sliding[track='#{$track}'] ion-label {
+    border-left: 2px solid $value;
+    padding-left: 10px;
+  }
+}

+ 27 - 0
src/app/sample-detail/sample-detail.page.spec.ts

@@ -0,0 +1,27 @@
+import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { SampleDetailPage } from './sample-detail.page';
+
+describe('SampleDetailPage', () => {
+  let component: SampleDetailPage;
+  let fixture: ComponentFixture<SampleDetailPage>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ SampleDetailPage ],
+      schemas: [CUSTOM_ELEMENTS_SCHEMA],
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(SampleDetailPage);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 102 - 0
src/app/sample-detail/sample-detail.page.ts

@@ -0,0 +1,102 @@
+import { Component, OnInit } from '@angular/core';
+import { Storage } from '@ionic/storage'
+import { UserData } from '../../providers/user-data';
+import { Camera, CameraOptions } from '@ionic-native/camera/ngx';
+// import { PhotoService, Photo } from '../services/photo.service';
+
+@Component({
+  selector: 'app-sample-detail',
+  templateUrl: './sample-detail.page.html',
+  styleUrls: ['./sample-detail.page.scss'],
+})
+export class SampleDetailPage implements OnInit {
+
+  public photos = [];
+  constructor(
+    // public photoService: PhotoService,
+    private camera: Camera,
+    private storage: Storage,
+    public userData: UserData) { }
+  defaultHref = '';
+  sdDocument = ''
+  sdMan = ''
+  sdpPost = ''
+  sdpModifydate = ""
+  sampleDetailList = []
+  ngOnInit() {
+    this.storage.get('sdId').then(async (val) => {
+      if (val) {
+        let data = await this.userData.getSampleDetail(val)
+        if (JSON.parse(data).data.length !== 0) {
+          this.sdpPost = JSON.parse(data).data[0].sdpPost
+          this.sdpModifydate = JSON.parse(data).data[0].sdpModifydate
+          this.sampleDetailList = JSON.parse(data).data
+          for (let i of this.sampleDetailList) {
+            i.imgsrc = i.pictures[0].smallPicture
+            let data = await this.userData.getSampleQAlog(i.sdpId)
+            if (JSON.parse(data).data.length !== 0) {
+              i.qalog = JSON.parse(data).data[0].mark
+              i.imgUrl = JSON.parse(data).data[0].picture.split(",")[0]
+              // i.imgList = JSON.parse(data).data[0].picture.split(",")
+            }
+          }
+        }
+      }
+    });
+    this.storage.get('sdDocument').then((val) => {
+      this.sdDocument = val
+    })
+  }
+  ionViewDidEnter() {
+    this.defaultHref = `/sample-table`;
+  }
+  takePicture(sample) {
+    const options: CameraOptions = {
+      quality: 10,
+      destinationType: this.camera.DestinationType.DATA_URL,
+      encodingType: this.camera.EncodingType.JPEG,
+      mediaType: this.camera.MediaType.PICTURE
+    }
+
+    this.camera.getPicture(options).then((imageData) => {
+      // sample.imgList.push(
+      //   'data:image/jpeg;base64,' + imageData
+      // )
+      sample.imgUrl = 'data:image/jpeg;base64,' + imageData
+      sample.imgData = imageData
+      // sample.imgData.push(imageData)
+    }, (err) => {
+      // Handle error
+      console.log("Camera issue: " + err);
+    });
+  }
+  async saveDetail() {
+    for (let i of this.sampleDetailList) {
+      if (i.qalog && i.imgData) {
+        let form = {
+          sdpId: i.sdpId,
+          mark: i.qalog,
+          files: i.imgData
+        }
+        await this.userData.saveSampleDetail(form)
+      }
+    }
+  }
+
+  // base64转blob
+  dataURLtoFile(dataURI, type) {
+    let binary = atob(dataURI.split(',')[1]);
+    let array = [];
+    for (let i = 0; i < binary.length; i++) {
+      array.push(binary.charCodeAt(i));
+    }
+    return new Blob([new Uint8Array(array)], { type: type });
+  }
+
+  deletePicture(sample) {
+    sample.imgUrl = ''
+    sample.imgData = ''
+    // sample.imgList.splice(index)
+    // sample.imgData.splice(index)
+  }
+}

+ 26 - 0
src/app/sample-table/sample-table.module.ts

@@ -0,0 +1,26 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormsModule } from '@angular/forms';
+import { Routes, RouterModule } from '@angular/router';
+
+import { IonicModule } from '@ionic/angular';
+
+import { SampleTablePage } from './sample-table.page';
+
+const routes: Routes = [
+  {
+    path: '',
+    component: SampleTablePage
+  }
+];
+
+@NgModule({
+  imports: [
+    CommonModule,
+    FormsModule,
+    IonicModule,
+    RouterModule.forChild(routes)
+  ],
+  declarations: [SampleTablePage]
+})
+export class SampleTablePageModule {}

+ 71 - 0
src/app/sample-table/sample-table.page.html

@@ -0,0 +1,71 @@
+<ion-header>
+  <ion-toolbar>
+    <ion-buttons slot="start">
+      <ion-back-button [defaultHref]="defaultHref"></ion-back-button>
+    </ion-buttons>
+    <ion-title>样品单列表</ion-title>
+  </ion-toolbar>
+</ion-header>
+
+<ion-content>
+  <!-- <ion-item-sliding>
+    <ion-item-options side="start">
+      <ion-item-option (click)="favorite(item)">Favorite</ion-item-option>
+      <ion-item-option color="danger" (click)="share(item)">Share</ion-item-option>
+    </ion-item-options>
+
+    <ion-item>
+      <ion-label>Item Options</ion-label>
+    </ion-item>
+
+    <ion-item-options side="end">
+      <ion-item-option (click)="unread(item)">Unread</ion-item-option>
+    </ion-item-options>
+  </ion-item-sliding> -->
+  <ion-card *ngFor="let sample of sampleList" (click)="getDetail(sample)">
+    <!-- <ion-item-sliding>
+      <ion-item> -->
+    <ion-card-content class="sample-content">
+      <div class="sample-title">
+        <ion-icon name="document"></ion-icon>
+        <ion-label>样品单号:</ion-label>
+        <ion-label>{{sample.sdDocument}}</ion-label>
+      </div>
+      <div class="sample-column">
+        <ion-icon name="man"></ion-icon>
+        <ion-label>下单人: </ion-label>
+        <ion-label>{{sample.sdMan}}</ion-label>
+      </div>
+      <div class="sample-column">
+        <ion-icon name="time"></ion-icon>
+        <ion-label>交样时间: </ion-label>
+        <ion-label>{{sample.sdFinishDate}}</ion-label>
+      </div>
+      <div class="sample-column">
+        <ion-icon name="time"></ion-icon>
+        <ion-label>下单时间:{{sample.sdCreateDate}}</ion-label>
+        <ion-label></ion-label>
+      </div>
+      <div class="sample-column">
+        <ion-icon name="business"></ion-icon>
+        <ion-label>客户名称: </ion-label>
+        <ion-label>{{sample.sdSelf}}</ion-label>
+      </div>
+<!--      <div class="sample-column">-->
+<!--        <ion-icon name="contact"></ion-icon>-->
+<!--        <ion-label>客户联系人: </ion-label>-->
+<!--        <ion-label>{{sample.cfullname}}</ion-label>-->
+<!--      </div>-->
+      <div class="sample-column">
+        <ion-icon name="flag"></ion-icon>
+        <ion-label>标记: </ion-label>
+        <ion-label>{{sample.sdRemark}}</ion-label>
+      </div>
+    </ion-card-content>
+    <!-- </ion-item>
+      <ion-item-options side="end">
+        <ion-item-option (click)="deleteSample(sample);$event.stopPropagation()">删除</ion-item-option>
+      </ion-item-options>
+    </ion-item-sliding> -->
+  </ion-card>
+</ion-content>

+ 17 - 0
src/app/sample-table/sample-table.page.scss

@@ -0,0 +1,17 @@
+.sample-content{
+    padding-top: 0;
+    width: 100%;
+}
+.sample-title {
+    border-bottom: 1px solid #bfb4b4;
+    padding-bottom: 10px;
+    padding-top: 10px;
+    padding-left: 10px;
+    font-size: 20px;
+    color:var(--ion-color-primary);
+}
+.sample-column {
+    padding-top: 8px;
+    color:#000;
+    font-size: 17px;
+}

+ 27 - 0
src/app/sample-table/sample-table.page.spec.ts

@@ -0,0 +1,27 @@
+import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { SampleTablePage } from './sample-table.page';
+
+describe('SampleTablePage', () => {
+  let component: SampleTablePage;
+  let fixture: ComponentFixture<SampleTablePage>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ SampleTablePage ],
+      schemas: [CUSTOM_ELEMENTS_SCHEMA],
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(SampleTablePage);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 33 - 0
src/app/sample-table/sample-table.page.ts

@@ -0,0 +1,33 @@
+import { Component, OnInit } from '@angular/core';
+import { Router } from '@angular/router';
+import { Storage } from '@ionic/storage'
+
+@Component({
+  selector: 'app-sample-table',
+  templateUrl: './sample-table.page.html',
+  styleUrls: ['./sample-table.page.scss'],
+})
+export class SampleTablePage implements OnInit {
+  constructor(private router: Router, private storage: Storage ) { }
+  sampleList = []
+  defaultHref = '';
+  ngOnInit() {
+    this.storage.get('sample-table-data').then((val) => {
+      if (val) {
+        this.sampleList = JSON.parse(val).data
+      }
+    });
+  }
+  ionViewDidEnter() {
+    this.defaultHref = `/sample`;
+  }
+  getDetail(sample) {
+    this.storage.set('sdId',sample.sdId).then(()=>{
+      this.router.navigateByUrl('/sample-detail')
+    })
+    this.storage.set('sdDocument',sample.sdDocument)
+  }
+  deleteSample(sample) {
+    console.log(sample)
+  }
+}

+ 26 - 0
src/app/sample/sample.module.ts

@@ -0,0 +1,26 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormsModule } from '@angular/forms';
+import { Routes, RouterModule } from '@angular/router';
+
+import { IonicModule } from '@ionic/angular';
+
+import { SamplePage } from './sample.page';
+
+const routes: Routes = [
+  {
+    path: '',
+    component: SamplePage
+  }
+];
+
+@NgModule({
+  imports: [
+    CommonModule,
+    FormsModule,
+    IonicModule,
+    RouterModule.forChild(routes)
+  ],
+  declarations: [SamplePage]
+})
+export class SamplePageModule {}

+ 53 - 0
src/app/sample/sample.page.html

@@ -0,0 +1,53 @@
+<ion-header>
+  <ion-toolbar>
+    <ion-buttons slot="start">
+      <ion-menu-button></ion-menu-button>
+    </ion-buttons>
+    <ion-title>样品单管理</ion-title>
+    <ion-buttons slot="end">
+      <ion-button (click)="clear()">
+        清空
+      </ion-button>
+    </ion-buttons>
+  </ion-toolbar>
+</ion-header>
+
+<ion-content>
+  <ion-list>
+    <ion-item>
+      <ion-label>样品单号:</ion-label>
+      <ion-input [(ngModel)]="sampleInfo.sdDocument"></ion-input>
+    </ion-item>
+    <!-- <ion-item>
+      <ion-label>交样时间(起):</ion-label>
+      <ion-datetime [(ngModel)]="sampleInfo.sdFinishDateLt"></ion-datetime>
+    </ion-item>
+    <ion-item>
+      <ion-label>交样时间(止):</ion-label>
+      <ion-datetime [(ngModel)]="sampleInfo.sdFinishDateGt"></ion-datetime>
+    </ion-item> -->
+    <ion-item>
+      <ion-label>下单时间(起):</ion-label>
+      <ion-datetime [(ngModel)]="sampleInfo.sdCreateDateGt"></ion-datetime>
+    </ion-item>
+    <ion-item>
+      <ion-label>下单时间(止):</ion-label>
+      <ion-datetime [(ngModel)]="sampleInfo.sdCreateDateLt"></ion-datetime>
+    </ion-item>
+    <!-- <ion-item>
+      <ion-label>客 户:</ion-label>
+      <ion-input [(ngModel)]="sampleInfo.sdDocument"></ion-input>
+    </ion-item> -->
+    <!-- <ion-item>
+      <ion-label>状 态:</ion-label>
+      <ion-input [(ngModel)]="sampleInfo.sdStatus"></ion-input>
+    </ion-item> -->
+    <ion-item>
+      <ion-label>跟单 QA:</ion-label>
+      <ion-input [(ngModel)]="sampleInfo.sdMan"></ion-input>
+    </ion-item>
+  </ion-list>
+  <div class="ion-padding">
+    <ion-button color="primary" expand="block" (click)="search()">查 询</ion-button>
+  </div>
+</ion-content>

+ 0 - 0
src/app/sample/sample.page.scss


+ 27 - 0
src/app/sample/sample.page.spec.ts

@@ -0,0 +1,27 @@
+import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { SamplePage } from './sample.page';
+
+describe('SamplePage', () => {
+  let component: SamplePage;
+  let fixture: ComponentFixture<SamplePage>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ SamplePage ],
+      schemas: [CUSTOM_ELEMENTS_SCHEMA],
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(SamplePage);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 83 - 0
src/app/sample/sample.page.ts

@@ -0,0 +1,83 @@
+import { Component, OnInit } from '@angular/core';
+import { UserData } from '../../providers/user-data';
+
+@Component({
+  selector: 'app-sample',
+  templateUrl: './sample.page.html',
+  styleUrls: ['./sample.page.scss'],
+})
+export class SamplePage implements OnInit {
+  sampleInfo = {
+    sdDocument: '',
+    sdFinishDateLt: '',
+    sdFinishDateGt: '',
+    sdCreateDateLt: '',
+    sdCreateDateGt: '',
+    sdStatus: '',
+    sdMan: ''
+  };
+  constructor(
+    public userData: UserData
+  ) { }
+
+  ngOnInit() { }
+  search() {
+    this.userData.getSampleTableData(this.getSerchForm())
+  }
+
+  getSerchForm() {
+    let queryForm = {
+      query: {
+        bool: {
+          must: [],
+          must_not: [],
+          should: []
+        }
+      },
+      from: 0,
+      size: 10,
+      sort: [],
+      aggs: {}
+    };
+    if (this.sampleInfo.sdDocument) {
+      let prefix = {}
+      prefix['sdDocument.keyword'] = this.sampleInfo.sdDocument
+      queryForm.query.bool.must.push({
+        prefix: prefix
+      })
+    }
+    if (this.sampleInfo.sdCreateDateGt || this.sampleInfo.sdCreateDateLt) {
+      let range = {
+        sdCreateDate: {}
+      }
+      if (this.sampleInfo.sdCreateDateGt) {
+        range.sdCreateDate['gt'] = new Date(this.sampleInfo.sdCreateDateGt).getTime()
+      }
+      if (this.sampleInfo.sdCreateDateLt) {
+        range.sdCreateDate['lt'] = new Date(this.sampleInfo.sdCreateDateLt).getTime()
+      }
+      queryForm.query.bool.must.push({
+        range: range
+      })
+    }
+    if (this.sampleInfo.sdMan) {
+      let prefix = {}
+      prefix['sdMan.keyword'] = this.sampleInfo.sdMan
+      queryForm.query.bool.must.push({
+        prefix: prefix
+      })
+    }
+     return queryForm
+  }
+  clear() {
+    this.sampleInfo = {
+      sdDocument: '',
+      sdFinishDateLt: '',
+      sdFinishDateGt: '',
+      sdCreateDateLt: '',
+      sdCreateDateGt: '',
+      sdStatus: '',
+      sdMan: ''
+    }
+  }
+}

+ 26 - 0
src/app/store-pending/store-pending.module.ts

@@ -0,0 +1,26 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormsModule } from '@angular/forms';
+import { Routes, RouterModule } from '@angular/router';
+
+import { IonicModule } from '@ionic/angular';
+
+import { StorePendingPage } from './store-pending.page';
+
+const routes: Routes = [
+  {
+    path: '',
+    component: StorePendingPage
+  }
+];
+
+@NgModule({
+  imports: [
+    CommonModule,
+    FormsModule,
+    IonicModule,
+    RouterModule.forChild(routes)
+  ],
+  declarations: [StorePendingPage]
+})
+export class StorePendingPageModule {}

+ 31 - 0
src/app/store-pending/store-pending.page.html

@@ -0,0 +1,31 @@
+<ion-header>
+  <ion-toolbar>
+    <ion-buttons slot="start">
+      <ion-menu-button></ion-menu-button>
+    </ion-buttons>
+    <ion-title>待验货物</ion-title>
+  </ion-toolbar>
+</ion-header>
+
+<ion-content>
+  <ion-card *ngFor="let pending of pendingList">
+    <ion-card-content class="pending-content">
+      <ion-item lines="none">
+        <span>产品图片:</span>
+        <img slot="end" [src]="pending.imgsrc" class="title-image"/>
+      </ion-item>
+      <ion-item>
+        <span>入库单号:{{pending.rkCode}}</span>
+      </ion-item>
+      <ion-item>
+        <span>我司货号:{{pending.scpCode}}</span>
+      </ion-item>
+      <ion-item>
+        <span>中文品名:{{pending.scpCnname}} </span>
+      </ion-item>
+      <ion-item>
+        <span>仓位说明:{{pending.storelocation}}</span>
+      </ion-item>
+    </ion-card-content>
+  </ion-card>
+</ion-content>

+ 7 - 0
src/app/store-pending/store-pending.page.scss

@@ -0,0 +1,7 @@
+.title-image {
+    width: auto;
+    height: 60px;
+}
+span {
+    font-size: 14px;
+}

+ 27 - 0
src/app/store-pending/store-pending.page.spec.ts

@@ -0,0 +1,27 @@
+import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { StorePendingPage } from './store-pending.page';
+
+describe('StorePendingPage', () => {
+  let component: StorePendingPage;
+  let fixture: ComponentFixture<StorePendingPage>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ StorePendingPage ],
+      schemas: [CUSTOM_ELEMENTS_SCHEMA],
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(StorePendingPage);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 33 - 0
src/app/store-pending/store-pending.page.ts

@@ -0,0 +1,33 @@
+import { Component, OnInit } from '@angular/core';
+import { UserData } from '../../providers/user-data';
+
+@Component({
+  selector: 'app-store-pending',
+  templateUrl: './store-pending.page.html',
+  styleUrls: ['./store-pending.page.scss'],
+})
+export class StorePendingPage implements OnInit {
+
+  pendingList = [1]
+  current: number = 1
+  size: number = 10
+  constructor(public userData: UserData) { }
+
+  ngOnInit() {
+    
+  }
+
+  ionViewDidEnter() {
+    this.getList()
+  }
+
+  async getList() {
+    let data = await this.userData.getStorePendingList(this.current, this.size)
+    this.pendingList = data
+    for(let i of this.pendingList) {
+      if(i["pictures"] && i["pictures"].length!==0) {
+        i["imgsrc"] = i["pictures"][0].smallPicture
+      }
+    }
+  }
+}

+ 26 - 0
src/app/store-qc-detail/store-qc-detail.module.ts

@@ -0,0 +1,26 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormsModule } from '@angular/forms';
+import { Routes, RouterModule } from '@angular/router';
+
+import { IonicModule } from '@ionic/angular';
+
+import { StoreQCDetailPage } from './store-qc-detail.page';
+
+const routes: Routes = [
+  {
+    path: '',
+    component: StoreQCDetailPage
+  }
+];
+
+@NgModule({
+  imports: [
+    CommonModule,
+    FormsModule,
+    IonicModule,
+    RouterModule.forChild(routes)
+  ],
+  declarations: [StoreQCDetailPage]
+})
+export class StoreQCDetailPageModule {}

+ 132 - 0
src/app/store-qc-detail/store-qc-detail.page.html

@@ -0,0 +1,132 @@
+<ion-header>
+  <ion-toolbar>
+    <ion-buttons slot="start">
+      <ion-back-button [defaultHref]="defaultHref"></ion-back-button>
+    </ion-buttons>
+    <ion-title>QC验货初检详情</ion-title>
+    <!-- <ion-popover-controller></ion-popover-controller> -->
+    <!-- <ion-buttons slot="end" (click)="presentPopover($event)">
+      <ion-button>
+        <ion-icon name="more"></ion-icon>
+      </ion-button>
+    </ion-buttons> -->
+    <!-- <ion-buttons slot="end"  *ngIf="QCdetails===null">
+      <ion-button (click)="recordQC()">
+        记录
+      </ion-button>
+      <ion-button (click)="createQC()">
+        生成
+      </ion-button>
+    </ion-buttons> -->
+  </ion-toolbar>
+</ion-header>
+
+<ion-content>
+  <ion-list *ngIf="QCdetails!==null">
+    <ion-item lines="none">
+      <span class="qc-title">初检报告编号:{{qcData.code}}</span>
+    </ion-item>
+    <ion-item>
+      <span>操作人:{{qcData.operator}} </span>
+    </ion-item>
+    <ion-item>
+      <span>修改时间:{{qcData.modifiedtime}}</span>
+    </ion-item>
+    <ion-item lines="none" *ngIf="qcData.details.length===0">
+      <ion-label color="danger">无详情</ion-label>
+    </ion-item>
+  </ion-list>
+  <ion-list *ngFor="let qc of qcData.details">
+    <ion-item-group>
+      <ion-item-divider sticky>
+        <ion-label>
+          初检单详情
+        </ion-label>
+      </ion-item-divider>
+    </ion-item-group>
+    <ion-item>
+      <ion-label>产品图片:</ion-label>
+      <ion-img [src]="qc.pictures[0].smallPicture" class="qc-product-img"></ion-img>
+    </ion-item>
+    <ion-item>
+      <ion-label>
+        我司货号:
+      </ion-label>
+      <ion-input [(ngModel)]="qc.scpCode"></ion-input>
+    </ion-item>
+    <ion-item>
+      <ion-label>
+        客户货号:
+      </ion-label>
+      <ion-input [(ngModel)]="qc.scpCustomercode"></ion-input>
+    </ion-item>
+    <ion-item>
+      <ion-label>
+        中文品名:
+      </ion-label>
+      <ion-input [(ngModel)]="qc.scpCnname"></ion-input>
+    </ion-item>
+    <ion-item>
+      <ion-label>
+        抽检箱数:
+      </ion-label>
+      <ion-input [(ngModel)]="qc.checkboxcount"></ion-input>
+    </ion-item>
+    <ion-item>
+      <ion-label>
+        抽检数量:
+      </ion-label>
+      <ion-input [(ngModel)]="qc.checkcount"></ion-input>
+    </ion-item>
+    <ion-item>
+      <ion-label>
+        瑕疵数量:
+      </ion-label>
+      <ion-input [(ngModel)]="qc.badcount"></ion-input>
+    </ion-item>
+    <ion-item>
+      <ion-label>
+        处理意见:
+      </ion-label>
+      <ion-item slot="end">
+        <ion-checkbox [(ngModel)]="qc.deal" readonly></ion-checkbox>
+        <ion-label *ngIf="qc.deal">通过</ion-label>
+        <ion-label *ngIf="!qc.deal" color="danger">未通过</ion-label>
+      </ion-item>
+    </ion-item>
+    <ion-item>
+      <ion-label>
+        QA日志:
+      </ion-label>
+      <ion-input [(ngModel)]="qc.qalog" readonly></ion-input>
+      <!-- <ion-icon name="camera" slot="end" (click)="takePicture(qc)"></ion-icon> -->
+    </ion-item>
+    <ion-item>
+      <ion-label>qa日志图片:</ion-label>
+      <ion-thumbnail *ngIf="qc.qaimgUrl">
+        <ion-img [src]="qc.qaimgUrl"></ion-img>
+      </ion-thumbnail>
+      <!-- <ion-icon *ngIf="qc.showPicture" name="close-circle-outline" (click)="deletePicture(qc)" slot="end"> -->
+      <!-- </ion-icon> -->
+    </ion-item>
+    <ion-item>
+      <ion-label>
+        QC日志:
+      </ion-label>
+      <ion-input [(ngModel)]="qc.qclog"></ion-input>
+      <ion-icon name="camera" slot="end" (click)="takePicture(qc)"></ion-icon>
+    </ion-item>
+    <ion-item>
+      <ion-label>QC日志图片:</ion-label>
+      <ion-thumbnail *ngIf="qc.qcimgUrl">
+        <ion-img [src]="qc.qcimgUrl"></ion-img>
+      </ion-thumbnail>
+      <ion-icon *ngIf="qc.qcimgUrl" name="close-circle-outline" (click)="deletePicture(qc)" slot="end">
+      </ion-icon>
+    </ion-item>
+  </ion-list>
+  <div class="ion-padding">
+    <ion-button color="primary" type="submit" expand="block" (click)="addQClog()">
+      添加QC日志</ion-button>
+  </div>
+</ion-content>

+ 6 - 0
src/app/store-qc-detail/store-qc-detail.page.scss

@@ -0,0 +1,6 @@
+.qc-title {
+    color:var(--ion-color-primary, #3880ff);
+}
+.qc-product-img {
+    height: 80px;
+}

+ 27 - 0
src/app/store-qc-detail/store-qc-detail.page.spec.ts

@@ -0,0 +1,27 @@
+import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { StoreQCDetailPage } from './store-qc-detail.page';
+
+describe('StoreQCDetailPage', () => {
+  let component: StoreQCDetailPage;
+  let fixture: ComponentFixture<StoreQCDetailPage>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ StoreQCDetailPage ],
+      schemas: [CUSTOM_ELEMENTS_SCHEMA],
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(StoreQCDetailPage);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 130 - 0
src/app/store-qc-detail/store-qc-detail.page.ts

@@ -0,0 +1,130 @@
+import { Component, OnInit } from '@angular/core';
+import { Storage } from '@ionic/storage'
+import { UserData } from '../../providers/user-data';
+import { Camera, CameraOptions } from '@ionic-native/camera/ngx';
+// import { FullScreenImage } from '@ionic-native/full-screen-image/ngx';
+
+// import { PopoverController } from '@ionic/angular'
+// import { PopoverPage } from '../qc-popover/qc-popover';
+
+@Component({
+  selector: 'app-store-qc-detail',
+  templateUrl: './store-qc-detail.page.html',
+  styleUrls: ['./store-qc-detail.page.scss'],
+})
+export class StoreQCDetailPage implements OnInit {
+
+  defaultHref = ""
+  qcData = {}
+  QCdetails = ''
+  pId = ''
+  sscId = ''
+  constructor(private storage: Storage,
+    // private fullScreenImage: FullScreenImage,
+    // public popoverCtrl: PopoverController,
+    private camera: Camera,
+    public userData: UserData) { }
+
+  ngOnInit() {
+    this.storage.get('QCdetails').then((val) => {
+      this.QCdetails = JSON.parse(val)
+    });
+    this.storage.get('qc-pId').then((val) => {
+      this.pId = val
+    });
+    this.storage.get('qc-sscId').then((val) => {
+      this.sscId = val
+    });
+  }
+
+  ionViewDidEnter() {
+    // console.log(this.fullScreenImage)
+    this.getDetail()
+  }
+
+  async getDetail() {
+    if (this.QCdetails) {
+      this.qcData = this.QCdetails
+      console.log(this.qcData)
+      for (let i of this.qcData['details']) {
+        // 获取QA日志
+        let qalogdata = await this.userData.getQAlog(i.sscId, i.pid)
+        if (JSON.parse(qalogdata).data.length !== 0) {
+          i.qalog = JSON.parse(qalogdata).data[0].mark
+          i.qaimgUrl = JSON.parse(qalogdata).data[0].picture.split(",")[0]
+        }
+        let qclogdata = await this.userData.getQClog(i.sscId, i.pid)
+        if (JSON.parse(qclogdata).data.length !== 0) {
+          i.qclog = JSON.parse(qclogdata).data[0].mark
+          i.qcimgUrl = JSON.parse(qclogdata).data[0].picture.split(",")[0]
+        }
+        // 处理意见转换boolean
+        if (i.dealpropose == 1) {
+          i.deal = true
+        } else {
+          i.deal = false
+        }
+      }
+      this.defaultHref = `/store-qc`;
+    }
+    // if (this.pId && this.sscId) {
+    //   let data = await this.userData.getQCDetail(this.pId, this.sscId)
+    //   this.defaultHref = `/store-qc-scanning`;
+    //   this.qcData['details'] = new Array(data)
+    // }
+  }
+  takePicture(qc) {
+    const options: CameraOptions = {
+      quality: 10,
+      destinationType: this.camera.DestinationType.DATA_URL,
+      encodingType: this.camera.EncodingType.PNG,
+      mediaType: this.camera.MediaType.PICTURE
+    }
+
+    this.camera.getPicture(options).then((imageData) => {
+      // console.log(imageData)
+      qc.showPicture = true
+      qc.imgData = imageData
+      qc.qcimgUrl = 'data:image/jpeg;base64,' + imageData
+    }, (err) => {
+      // Handle error
+      console.log("Camera issue: " + err);
+    });
+  }
+
+  deletePicture(qc) {
+    qc.imgData = ''
+    qc.qcimgUrl = ''
+  }
+
+  // async presentPopover(event: Event) {
+  //   const popover = await this.popoverCtrl.create({
+  //     component: PopoverPage,
+  //     event: event,
+  //     translucent: true
+  //   });
+  //   return await popover.present();
+  // }
+
+
+  async createQC() {
+    await this.userData.createQC(this.qcData['details'])
+  }
+
+  async addQClog() {
+    for (let i of this.qcData['details']) {
+      // console.log(i)
+      if (i.qclog && i.imgData) {
+        // let file = []
+        // file.push(i.imgData)
+        let form = {
+          files: i.imgData,
+          mark: i.qclog,
+          pId: i.pid,
+          sscId: i.sscId
+        }
+        await this.userData.addQClog(form)
+      }
+    }
+  }
+}

+ 26 - 0
src/app/store-qc-scanning/store-qc-scanning.module.ts

@@ -0,0 +1,26 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormsModule } from '@angular/forms';
+import { Routes, RouterModule } from '@angular/router';
+
+import { IonicModule } from '@ionic/angular';
+
+import { StoreQCScanningPage } from './store-qc-scanning.page';
+
+const routes: Routes = [
+  {
+    path: '',
+    component: StoreQCScanningPage
+  }
+];
+
+@NgModule({
+  imports: [
+    CommonModule,
+    FormsModule,
+    IonicModule,
+    RouterModule.forChild(routes)
+  ],
+  declarations: [StoreQCScanningPage]
+})
+export class StoreQCScanningPageModule {}

+ 138 - 0
src/app/store-qc-scanning/store-qc-scanning.page.html

@@ -0,0 +1,138 @@
+<ion-header>
+  <ion-toolbar>
+    <ion-buttons slot="start">
+      <ion-menu-button></ion-menu-button>
+    </ion-buttons>
+    <ion-title>QC扫描</ion-title>
+    <ion-buttons slot="end">
+      <ion-button [disabled]="storeQCList.length===0" (click)="generateQC()">
+        生成
+      </ion-button>
+    </ion-buttons>
+  </ion-toolbar>
+</ion-header>
+
+<ion-content>
+  <ion-item>
+    <ion-label>条形码编号:</ion-label>
+    <ion-input #scanInput clear-on-edit (ionChange)="getStoreQCDetail()" [(ngModel)]="scanCode"></ion-input>
+  </ion-item>
+  <ion-list *ngFor="let qc of storeQCDetailList">
+    <ion-item-group>
+      <ion-item-divider sticky>
+        <ion-label>
+          初检单详情
+        </ion-label>
+      </ion-item-divider>
+    </ion-item-group>
+    <ion-item>
+      <ion-label>
+        我司货号:
+      </ion-label>
+      <ion-input [(ngModel)]="qc.scpCode"></ion-input>
+    </ion-item>
+    <ion-item>
+      <ion-label>
+        客户货号:
+      </ion-label>
+      <ion-input [(ngModel)]="qc.scpCustomercode"></ion-input>
+    </ion-item>
+    <ion-item>
+      <ion-label>
+        中文品名:
+      </ion-label>
+      <ion-input [(ngModel)]="qc.scpCnname"></ion-input>
+    </ion-item>
+    <ion-item>
+      <ion-label>
+        抽检箱数:
+      </ion-label>
+      <ion-input [(ngModel)]="qc.checkboxcount"></ion-input>
+    </ion-item>
+    <ion-item>
+      <ion-label>
+        抽检数量:
+      </ion-label>
+      <ion-input [(ngModel)]="qc.checkcount"></ion-input>
+    </ion-item>
+    <ion-item>
+      <ion-label>
+        瑕疵数量:
+      </ion-label>
+      <ion-input [(ngModel)]="qc.badcount"></ion-input>
+    </ion-item>
+    <ion-item>
+      <ion-label>
+        处理意见:
+      </ion-label>
+      <ion-item slot="end">
+        <ion-checkbox [(ngModel)]="qc.deal" readonly></ion-checkbox>
+        <ion-label *ngIf="qc.deal">通过</ion-label>
+        <ion-label *ngIf="!qc.deal" color="danger">未通过s</ion-label>
+      </ion-item>
+    </ion-item>
+    <ion-item>
+      <ion-label>
+        QA日志:
+      </ion-label>
+      <ion-input [(ngModel)]="qc.qalog" readonly></ion-input>
+      <!-- <ion-icon name="camera" slot="end" (click)="takePicture(qc)"></ion-icon> -->
+    </ion-item>
+    <ion-item>
+      <ion-label>qa日志图片:</ion-label>
+      <ion-thumbnail *ngIf="qc.qaimgUrl">
+        <ion-img [src]="qc.qaimgUrl"></ion-img>
+      </ion-thumbnail>
+      <!-- <ion-icon *ngIf="qc.showPicture" name="close-circle-outline" (click)="deletePicture(qc)" slot="end"> -->
+      <!-- </ion-icon> -->
+    </ion-item>
+    <ion-item>
+      <ion-label>
+        QC日志:
+      </ion-label>
+      <ion-input [(ngModel)]="qc.qclog"></ion-input>
+      <ion-icon name="camera" slot="end" (click)="takePicture(qc)"></ion-icon>
+    </ion-item>
+    <ion-item>
+      <ion-label>QC日志图片:</ion-label>
+      <ion-thumbnail *ngIf="qc.qcimgUrl">
+        <ion-img [src]="qc.qcimgUrl"></ion-img>
+      </ion-thumbnail>
+      <ion-icon *ngIf="qc.qcimgUrl" name="close-circle-outline" (click)="deletePicture(qc)" slot="end">
+      </ion-icon>
+    </ion-item>
+    <!-- <ion-item>
+      <ion-label>
+        跟单备注:
+      </ion-label>
+      <ion-input [(ngModel)]="qc.remark"></ion-input>
+      <ion-icon name="camera" slot="end" (click)="takePicture(qc)"></ion-icon>
+    </ion-item>
+    <ion-item>
+      <ion-label>备注图片:</ion-label>
+      <ion-thumbnail *ngIf="qc.imgUrl">
+        <ion-img [src]="qc.imgUrl"></ion-img>
+      </ion-thumbnail>
+      <ion-icon *ngIf="qc.imgUrl" name="close-circle-outline" (click)="deletePicture(qc)" slot="end">
+      </ion-icon>
+    </ion-item> -->
+  </ion-list>
+  <div class="ion-padding">
+    <ion-button [disabled]="storeQCDetailList.length===0" color="primary" type="submit" expand="block"
+      (click)="saveQCRecord()">
+      记 录</ion-button>
+  </div>
+  <ion-list>
+    <ion-item-group>
+      <ion-item-divider sticky>
+        <ion-label>
+          已扫描条形码编号
+        </ion-label>
+      </ion-item-divider>
+    </ion-item-group>
+    <ion-item *ngFor="let item of storeQCList index as i">
+      <ion-label color="primary" (click)="getStoreQCDetail(item)">{{item.scpCode}}({{item.scanCode}})</ion-label>
+      <ion-icon name="trash" (click)="deleteQCStore(item, i)"></ion-icon>
+    </ion-item>
+  </ion-list>
+</ion-content>

+ 0 - 0
src/app/store-qc-scanning/store-qc-scanning.page.scss


+ 27 - 0
src/app/store-qc-scanning/store-qc-scanning.page.spec.ts

@@ -0,0 +1,27 @@
+import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { StoreQCScanningPage } from './store-qc-scanning.page';
+
+describe('StoreQCScanningPage', () => {
+  let component: StoreQCScanningPage;
+  let fixture: ComponentFixture<StoreQCScanningPage>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ StoreQCScanningPage ],
+      schemas: [CUSTOM_ELEMENTS_SCHEMA],
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(StoreQCScanningPage);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 158 - 0
src/app/store-qc-scanning/store-qc-scanning.page.ts

@@ -0,0 +1,158 @@
+import { Component, OnInit, ViewChild } from '@angular/core';
+import { Router } from '@angular/router';
+import { Storage } from '@ionic/storage'
+import { Keyboard } from '@ionic-native/keyboard/ngx';
+import { UserData } from '../../providers/user-data';
+import { Camera, CameraOptions } from '@ionic-native/camera/ngx';
+
+@Component({
+  selector: 'app-store-qc-scanning',
+  templateUrl: './store-qc-scanning.page.html',
+  styleUrls: ['./store-qc-scanning.page.scss'],
+})
+export class StoreQCScanningPage implements OnInit {
+
+  scanCode = ''
+  storeQCList = []
+  storeQCDetailList = []
+  constructor(private router: Router,
+    private storage: Storage,
+    public userData: UserData,
+    private camera: Camera,
+    private keyboard: Keyboard) { }
+
+  @ViewChild('scanInput') scanInput;
+  ngOnInit() {
+  }
+
+  ionViewDidEnter() {
+    this.initialData()
+  }
+
+  initialData() {
+    this.storeQCDetailList = []
+    this.scanCode = ''
+    this.scanInput.setFocus();
+  }
+
+  // 获取扫描详情
+  async getStoreQCDetail(item) {
+    this.keyboard.hide()
+    if (item) {
+      this.scanCode = item.scanCode
+      this.storeQCDetailList = item
+    } else {
+      if (this.scanCode.split('_').length === 2) {
+        let filterData = []
+        filterData = this.storeQCList.filter(item => { return item.sscId == this.scanCode.split('_')[0] && item.pid == this.scanCode.split('_')[1] })
+        if (filterData.length !== 0) {
+          this.storeQCDetailList = filterData
+        } else {
+          let data = await this.userData.getQCDetail(Number(this.scanCode.split('_')[0]), Number(this.scanCode.split('_')[1]))
+          this.storeQCDetailList = new Array(data)
+        }
+        for (let i of this.storeQCDetailList) {
+          // 获取QA日志
+          let qalogdata = await this.userData.getQAlog(i.sscId, i.pid)
+          if (JSON.parse(qalogdata).data.length !== 0) {
+            i.qalog = JSON.parse(qalogdata).data[0].mark
+            i.qaimgUrl = JSON.parse(qalogdata).data[0].picture.split(",")[0]
+          }
+          let qclogdata = await this.userData.getQClog(i.sscId, i.pid)
+          if (JSON.parse(qclogdata).data.length !== 0) {
+            i.qclog = JSON.parse(qclogdata).data[0].mark
+            i.qcimgUrl = JSON.parse(qclogdata).data[0].picture.split(",")[0]
+          }
+          // 处理意见转换boolean
+          if (i.dealpropose == 1) {
+            i.deal = true
+          } else {
+            i.deal = false
+          }
+        }
+      }
+    }
+  }
+
+  // 生成QC验货初检报告
+  async generateQC() {
+    for (let i of this.storeQCList) {
+      if (i.deal) {
+        i.dealpropose = 1
+      } else {
+        i.dealpropose = 0
+      }
+    }
+    await this.userData.createQC(this.storeQCList)
+  }
+
+  // 记录数据
+  async saveQCRecord() {
+    let _this = this
+    // 是否已扫描记录过该数据
+    let filterData = []
+    filterData = this.storeQCList.filter(item => {
+      return item.sscId == this.storeQCDetailList[0].sscId && item.pid == this.storeQCDetailList[0].pid
+    })
+    // 有则更新
+    if (filterData.length !== 0) {
+      filterData = this.storeQCDetailList
+      // 无则加上  
+    } else {
+      this.storeQCList = this.storeQCList.concat(this.storeQCDetailList)
+    }
+    // 显示记录中的外销合同号
+    // this.scpCodes = []
+    for (let i of this.storeQCList) {
+      i.scanCode = this.scanCode
+      // this.scpCodes.push(i.scpCode)
+    }
+    this.addQClog()
+    this.initialData()
+  }
+
+  // 添加qc记录
+  async addQClog() {
+    for (let i of this.storeQCDetailList) {
+      // console.log(i)
+      if (i.qclog && i.imgData) {
+        // let file = []
+        // file.push(i.imgData)
+        let form = {
+          files: i.imgData,
+          mark: i.qclog,
+          pId: i.pid,
+          sscId: i.sscId
+        }
+        await this.userData.addQClog(form)
+      }
+    }
+  }
+
+  takePicture(qc) {
+    const options: CameraOptions = {
+      quality: 10,
+      destinationType: this.camera.DestinationType.DATA_URL,
+      encodingType: this.camera.EncodingType.JPEG,
+      mediaType: this.camera.MediaType.PICTURE
+    }
+
+    this.camera.getPicture(options).then((imageData) => {
+      // console.log(imageData)
+      qc.imgData = imageData
+      qc.qcimgUrl = 'data:image/jpeg;base64,' + imageData
+    }, (err) => {
+      // Handle error
+      console.log("Camera issue: " + err);
+    });
+  }
+
+  deletePicture(qc) {
+    qc.imgData = ''
+    qc.qcimgUrl = ''
+  }
+
+  deleteQCStore(store, index) {
+    this.storeQCList.splice(index)
+  }
+}

+ 26 - 0
src/app/store-qc/store-qc.module.ts

@@ -0,0 +1,26 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormsModule } from '@angular/forms';
+import { Routes, RouterModule } from '@angular/router';
+
+import { IonicModule } from '@ionic/angular';
+
+import { StoreQCPage } from './store-qc.page';
+
+const routes: Routes = [
+  {
+    path: '',
+    component: StoreQCPage
+  }
+];
+
+@NgModule({
+  imports: [
+    CommonModule,
+    FormsModule,
+    IonicModule,
+    RouterModule.forChild(routes)
+  ],
+  declarations: [StoreQCPage]
+})
+export class StoreQCPageModule {}

+ 29 - 0
src/app/store-qc/store-qc.page.html

@@ -0,0 +1,29 @@
+<ion-header>
+  <ion-toolbar>
+    <ion-buttons slot="start">
+      <ion-menu-button></ion-menu-button>
+    </ion-buttons>
+    <ion-title>QC验货初检报告</ion-title>
+  </ion-toolbar>
+</ion-header>
+
+<ion-content>
+  <ion-refresher slot="fixed" (ionRefresh)="doRefresh($event)">
+    <ion-refresher-content pullingIcon="arrow-dropdown" pullingText="加载中..." refreshingSpinner="circles"
+      refreshingText="刷新...">
+    </ion-refresher-content>
+  </ion-refresher>
+  <ion-card *ngFor="let qc of qcList" (click)="getQCdetail(qc)">
+    <ion-card-content>
+      <ion-item lines="none">
+        <span class="qc-title">初检报告编号:{{qc.code}}</span>
+      </ion-item>
+      <ion-item>
+        <span>操作人:{{qc.operator}} </span>
+      </ion-item>
+      <ion-item>
+        <span>修改时间:{{qc.modifiedtime}}</span>
+      </ion-item>
+    </ion-card-content>
+  </ion-card>
+</ion-content>

+ 3 - 0
src/app/store-qc/store-qc.page.scss

@@ -0,0 +1,3 @@
+.qc-title {
+    color:var(--ion-color-primary, #3880ff);
+}

+ 27 - 0
src/app/store-qc/store-qc.page.spec.ts

@@ -0,0 +1,27 @@
+import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { StoreQCPage } from './store-qc.page';
+
+describe('StoreQCPage', () => {
+  let component: StoreQCPage;
+  let fixture: ComponentFixture<StoreQCPage>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ StoreQCPage ],
+      schemas: [CUSTOM_ELEMENTS_SCHEMA],
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(StoreQCPage);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 39 - 0
src/app/store-qc/store-qc.page.ts

@@ -0,0 +1,39 @@
+import { Component, OnInit } from '@angular/core';
+import { UserData } from '../../providers/user-data';
+import { Storage } from '@ionic/storage'
+import { Router } from '@angular/router';
+
+@Component({
+  selector: 'app-store-qc',
+  templateUrl: './store-qc.page.html',
+  styleUrls: ['./store-qc.page.scss'],
+})
+export class StoreQCPage implements OnInit {
+
+  qcList = []
+  current: number = 1
+  size: number = 10
+  constructor(public userData: UserData, private storage: Storage, private router: Router ) { }
+
+  ngOnInit() {
+    this.getList()
+  }
+
+  async getList() {
+    let data = await this.userData.getQCList(this.current, this.size)
+    this.qcList = data
+  }
+
+  async doRefresh(event) {
+    await this.getList()
+    event.target.complete();    //告诉ion-refresher  更新数据
+  }
+
+  getQCdetail(details) {
+    this.storage.set('QCdetails',JSON.stringify(details)).then(()=>{
+      this.storage.remove('qc-pId')
+      this.storage.remove('qc-sscId')
+      this.router.navigateByUrl('/store-qc-detail')
+    })
+  }
+}

+ 0 - 0
src/app/store-sample-barcode/store-sample-barcode.module.ts


Some files were not shown because too many files changed in this diff