teddyhuang преди 5 години
родител
ревизия
bcddc40fe1
променени са 20 файла, в които са добавени 1760 реда и са изтрити 365 реда
  1. +1
    -0
      app/.idea/.gitignore
  2. +156
    -0
      app/public/obank_logo.svg
  3. +4
    -3
      app/src/App.vue
  4. +366
    -170
      app/src/components/AssetGroup.vue
  5. +114
    -35
      app/src/components/Home.vue
  6. +259
    -128
      app/src/components/Inventory.vue
  7. +20
    -16
      app/src/components/Login.vue
  8. +220
    -0
      app/src/components/MockSearch.vue
  9. +178
    -0
      app/src/components/Search.vue
  10. +201
    -0
      app/src/components/xxx.vue
  11. +10
    -3
      app/src/router/index.js
  12. +13
    -3
      src/main/java/com/moze/rms/config/JdbiFactory.java
  13. +23
    -2
      src/main/java/com/moze/rms/controller/AccountController.java
  14. +45
    -0
      src/main/java/com/moze/rms/controller/AssertGroupController.java
  15. +24
    -2
      src/main/java/com/moze/rms/controller/InventoryController.java
  16. +18
    -0
      src/main/java/com/moze/rms/dao/AccountDAO.java
  17. +49
    -0
      src/main/java/com/moze/rms/dao/AssertDAO.java
  18. +43
    -3
      src/main/java/com/moze/rms/dao/InventoryDAO.java
  19. +12
    -0
      src/main/java/com/moze/rms/entity/dto/SelectItemDTO.java
  20. +4
    -0
      src/main/java/com/moze/rms/entity/model/MappingCol.java

+ 1
- 0
app/.idea/.gitignore Целия файл

@@ -1,2 +1,3 @@
# Default ignored files
/workspace.xml
/inspectionProfiles/Project_Default.xml

+ 156
- 0
app/public/obank_logo.svg Целия файл

@@ -0,0 +1,156 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="圖層_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="498.15px" height="85px" viewBox="15.108 0 498.15 85" enable-background="new 15.108 0 498.15 85" xml:space="preserve">
<path fill="#FF8300" d="M132.896,51.625l-0.001,0.873c0,1.229,1.189,2.22,2.654,2.223c1.467,0.002,2.653-0.996,2.653-2.223
l0.002-0.872c0-1.226-1.191-2.219-2.657-2.217C134.084,49.404,132.895,50.402,132.896,51.625"/>
<path fill="#FF8300" d="M89.355,43.318l-0.003,0.873c0,1.229,1.146,2.222,2.557,2.222c1.406,0.004,2.55-0.995,2.551-2.222V43.32
c0-1.224-1.146-2.219-2.555-2.218C90.495,41.1,89.353,42.098,89.355,43.318"/>
<path fill="#FF8300" d="M95.272,43.318l-0.001,0.873c0,1.229,1.146,2.222,2.551,2.222c1.409,0.004,2.555-0.995,2.555-2.222
l0.002-0.871c-0.002-1.224-1.147-2.219-2.56-2.218C96.413,41.1,95.271,42.098,95.272,43.318"/>
<path fill="#FF8300" d="M101.187,43.318v0.873c0,1.229,1.145,2.222,2.555,2.222c1.409,0.004,2.553-0.995,2.553-2.222V43.32
c0-1.224-1.146-2.219-2.557-2.218C102.33,41.1,101.187,42.098,101.187,43.318"/>
<path fill="#FF8300" d="M190.238,51.516l-0.7,0.515c-0.981,0.721-1.1,2.223-0.271,3.349c0.828,1.127,2.299,1.454,3.277,0.732
l0.698-0.512c0.979-0.725,1.101-2.226,0.269-3.351C192.683,51.122,191.214,50.794,190.238,51.516"/>
<path fill="#403F41" d="M174.694,27.209l-3.322-4.221c-0.812-1.076-2.444-1.214-3.638-0.309c-1.198,0.902-1.516,2.505-0.698,3.585
l3.32,4.217c0.808,1.08,2.439,1.218,3.638,0.315C175.188,29.896,175.506,28.286,174.694,27.209"/>
<path fill="#403F41" d="M193.077,60.723l3.32,4.221c0.814,1.076,2.446,1.217,3.64,0.31c1.198-0.903,1.515-2.506,0.697-3.586
l-3.319-4.362c-0.809-1.078-2.439-1.218-3.636-0.314C192.584,57.891,192.264,59.646,193.077,60.723"/>
<path fill="#403F41" d="M169.316,22.081c-1.509,0-2.733,1.223-2.733,2.731v18.917v19.39c0,1.51,1.226,2.731,2.733,2.731
c1.509,0,2.734-1.223,2.734-2.731v-19.39V24.812C172.051,23.304,170.824,22.081,169.316,22.081"/>
<path fill="#403F41" d="M198.456,22.081c-1.51,0-2.736,1.223-2.736,2.731v18.917v19.39c0,1.51,1.228,2.731,2.736,2.731
c1.507,0,2.731-1.223,2.731-2.731v-19.39V24.812C201.188,23.304,199.963,22.081,198.456,22.081"/>
<path fill="#403F41" d="M174.495,35.918l10.719,14.454c0.798,1.085,2.426,1.242,3.634,0.356c1.21-0.889,1.545-2.487,0.745-3.576
L178.77,32.64c-0.797-1.091-2.425-1.246-3.638-0.36C173.925,33.162,173.7,34.827,174.495,35.918"/>
<path fill="#403F41" d="M223.518,47.062l0.008-0.008L223.518,47.062z"/>
<path fill="#403F41" d="M141.425,54.802h10.411c1.357,0.001,2.458-1.226,2.461-2.735c0-1.508-1.098-2.738-2.457-2.74h-10.404
c-1.36-0.003-2.462,1.225-2.465,2.734C138.965,53.568,140.069,54.799,141.425,54.802"/>
<path fill="#403F41" d="M75.087,46.493h11.07c1.356,0.001,2.456-1.226,2.461-2.734c0.001-1.51-1.097-2.737-2.458-2.738H75.096
c-1.359-0.006-2.463,1.221-2.467,2.732C72.625,45.261,73.729,46.491,75.087,46.493"/>
<path fill="#403F41" d="M103.84,60.309h-1.824v-0.002H86.318v-32.81h15.697v-0.008h3.266c1.153,0,2.007,0.208,2.979,0.871
c1.593,1.089,2.403,3.024,2.408,5.751c0.01,4.965-1.527,6.683-2.466,7.413c-0.36,0.281-1.178,0.942-1.178,2.375V43.9
c0,1.726,1.188,2.384,1.721,2.635c0.332,0.154,3.24,1.023,3.24,6.037C111.986,59.792,105.75,60.309,103.84,60.309 M113.599,43.902
c1.184-1.856,2.629-5.721,2.629-9.802c0-8.529-5.759-12.151-10.582-12.151h-3.63h-3.479H83.566c-1.522,0-2.758,1.243-2.758,2.773
v38.355c0,1.53,1.234,2.771,2.758,2.771h12.604h5.847h1.824c9.468,0,13.705-6.617,13.705-13.275
C117.545,47.691,115.367,45.666,113.599,43.902"/>
<path fill="#FF8300" d="M226.229,37.528l0.608,0.626c0.854,0.879,2.4,0.758,3.453-0.263c1.049-1.023,1.204-2.566,0.347-3.442
l-0.604-0.626c-0.856-0.875-2.404-0.758-3.45,0.267C225.529,35.11,225.374,36.654,226.229,37.528"/>
<path fill="#403F41" d="M242.311,65.807c-0.771,0-1.544-0.326-2.088-0.961l-14.276-16.943c-0.991-1.155-0.857-2.896,0.298-3.883
c1.157-0.992,2.896-0.858,3.886,0.297l14.272,16.944c0.99,1.153,0.858,2.895-0.298,3.884
C243.582,65.592,242.947,65.807,242.311,65.807"/>
<path fill="#403F41" d="M212.854,21.951c-1.522,0-2.758,1.234-2.758,2.753v19.051v19.298c0,1.521,1.234,2.754,2.758,2.754
c1.518,0,2.75-1.232,2.75-2.754V43.755V24.704C215.604,23.186,214.37,21.951,212.854,21.951"/>
<path fill="#403F41" d="M234.554,33.85l7.453-7.271c0.972-0.944,0.904-2.593-0.146-3.675c-1.054-1.081-2.697-1.197-3.671-0.248
l-7.451,7.265c-0.978,0.945-0.908,2.594,0.145,3.68C231.931,34.683,233.576,34.792,234.554,33.85"/>
<path fill="#403F41" d="M226.137,42.057l-7.454,7.266c-0.971,0.948-2.614,0.837-3.673-0.24c-1.055-1.082-1.127-2.728-0.153-3.677
l7.452-7.266c0.969-0.953,2.615-0.842,3.67,0.238C227.034,39.454,227.105,41.104,226.137,42.057"/>
<path fill="#FF8300" d="M42.479,56.62c4.024-0.006,9.558-1.964,10.323-6.166c0.046-0.24,0.095-0.624,0.092-0.802
c-0.191-0.855-1.019-0.281-1.424-0.104c-0.587,0.262-5.169,1.456-8.991,1.456c-3.82,0-8.404-1.194-8.993-1.456
c-0.401-0.178-1.229-0.752-1.421,0.104c-0.003,0.178,0.048,0.562,0.09,0.802C32.92,54.656,38.454,56.614,42.479,56.62"/>
<path fill="#403F41" d="M37.318,40.759l0.003-1.195c-0.003-1.677-1.567-3.039-3.498-3.034c-1.925-0.005-3.491,1.359-3.487,3.032
l-0.004,1.197c0,1.68,1.566,3.037,3.496,3.037C35.757,43.8,37.318,42.435,37.318,40.759"/>
<path fill="#403F41" d="M54.626,40.759l0.003-1.195c-0.003-1.677-1.57-3.039-3.5-3.034c-1.925-0.005-3.492,1.359-3.486,3.032
l-0.006,1.197c0,1.68,1.568,3.037,3.496,3.037C53.062,43.8,54.626,42.435,54.626,40.759"/>
<path fill="#FF8300" d="M59.803,23.662c-0.794,0-1.555,0.303-2.086,0.829c-1.158,1.149-1.164,3.028-0.016,4.188
c4.344,4.38,6.6,10.424,6.186,16.584c-0.389,5.715-2.979,10.939-7.298,14.711c-3.916,3.414-8.932,5.295-14.124,5.295
c-0.479,0-0.966-0.018-1.447-0.047c-8.098-0.574-15.104-5.552-18.294-12.99c-1.021-2.397-1.593-4.941-1.696-7.557
c-0.064-1.597-1.365-2.848-2.96-2.848l-0.117,0.003c-1.627,0.064-2.903,1.446-2.843,3.076c0.134,3.342,0.864,6.589,2.178,9.655
C21.349,64.05,30.26,70.395,40.54,71.119l0.088,0.007c0.62,0.042,1.256,0.063,1.893,0.063c6.588,0,12.967-2.4,17.961-6.756
c5.514-4.809,8.817-11.475,9.312-18.771c0.534-7.85-2.342-15.561-7.891-21.154C61.369,23.972,60.604,23.662,59.803,23.662"/>
<path fill="#403F41" d="M41.805,19.277c-0.027,0.263-0.021,0.53,0.025,0.802c0.017,0.077,0.029,0.152,0.046,0.225
c0.304,1.291,1.395,2.245,2.717,2.373c2.562,0.253,5.047,0.971,7.384,2.125c0.745,0.372,1.585,0.432,2.375,0.168
c0.786-0.265,1.423-0.819,1.793-1.561c0.322-0.648,0.412-1.396,0.245-2.1c-0.211-0.904-0.812-1.661-1.646-2.074
c-3.007-1.499-6.22-2.421-9.543-2.749c-0.822-0.082-1.628,0.163-2.27,0.684C42.288,17.696,41.89,18.445,41.805,19.277"/>
<path fill="#403F41" d="M26.355,25.312c0.149,0.222,0.325,0.423,0.53,0.602c0.062,0.052,0.121,0.099,0.18,0.144
c1.057,0.804,2.504,0.846,3.605,0.106c2.138-1.44,4.509-2.467,7.05-3.061c0.809-0.187,1.496-0.677,1.938-1.384
c0.437-0.705,0.575-1.537,0.39-2.343c-0.164-0.706-0.569-1.338-1.146-1.777c-0.738-0.562-1.684-0.765-2.589-0.554
c-3.274,0.759-6.339,2.089-9.107,3.954c-0.688,0.458-1.157,1.159-1.317,1.967C25.725,23.785,25.894,24.615,26.355,25.312"/>
<path fill="#403F41" d="M18.28,39.798c0.253,0.076,0.518,0.12,0.791,0.124c0.079,0.003,0.155,0.001,0.23,0
c1.323-0.053,2.471-0.941,2.848-2.215c0.735-2.468,1.912-4.773,3.493-6.844c0.505-0.66,0.722-1.477,0.614-2.3
c-0.113-0.824-0.533-1.556-1.191-2.058c-0.577-0.438-1.292-0.671-2.014-0.642c-0.927,0.035-1.786,0.479-2.354,1.22
c-2.041,2.669-3.558,5.646-4.509,8.845c-0.236,0.791-0.154,1.632,0.237,2.357C16.822,39.019,17.479,39.554,18.28,39.798"/>
<path fill="#403F41" d="M160.492,62.02l-17.291-38.312c-0.434-1.037-1.446-1.714-2.571-1.714c-0.006,0-0.01,0.001-0.015,0.001
s-0.012-0.001-0.016-0.001c-1.127,0-2.141,0.677-2.571,1.714L120.738,62.02c-0.591,1.418,0.088,3.037,1.513,3.621
c0.346,0.144,0.703,0.211,1.054,0.211c1.097,0,2.129-0.646,2.576-1.72l14.734-33.24l14.735,33.24c0.446,1.073,1.48,1.72,2.575,1.72
c0.352,0,0.709-0.067,1.055-0.211C160.405,65.057,161.082,63.438,160.492,62.02"/>
<path fill="#403F41" d="M405.429,49.82c0-0.77,0.701-1.197,1.623-1.197s1.538,0.429,1.538,1.197v7.654
c0,0.775-0.616,1.205-1.538,1.205c-0.879,0-1.623-0.43-1.623-1.205V49.82z"/>
<path fill="#403F41" d="M418.009,49.82c0-0.77,0.704-1.197,1.623-1.197c0.924,0,1.536,0.429,1.536,1.197v7.654
c0,0.775-0.612,1.205-1.536,1.205c-0.878,0-1.623-0.43-1.623-1.205V49.82z"/>
<path fill="#403F41" d="M374.546,41.286H356.82v-2.782c0-0.989,0.438-1.238,1.408-1.238h14.949c0.927,0,1.368,0.249,1.368,1.238
L374.546,41.286L374.546,41.286z M374.546,48.432H356.82v-4.168h17.727V48.432L374.546,48.432z M374.546,54.585
c0,0.945-0.441,1.243-1.368,1.243h-14.949c-0.97,0-1.408-0.298-1.408-1.243v-3.174h17.727L374.546,54.585L374.546,54.585z
M374.009,34.186h-8.706c0.005-0.004,0.005-0.013,0.011-0.018h-3.747c-0.002,0.005-0.005,0.014-0.011,0.018h-4.297
c-2.679,0-3.938,1.095-3.938,3.723V55.23c0,2.683,1.214,3.771,3.938,3.771h16.75c2.771,0,4.034-1.089,4.034-3.771V37.908
C378.043,35.28,376.78,34.186,374.009,34.186"/>
<path fill="#403F41" d="M345.058,46.348V57.93c-0.371,0.411-0.772,0.828-1.192,1.244h5.64c-0.278-0.4-0.55-0.822-0.809-1.296V45.555
c0-2.583-1.066-3.923-3.544-3.923h-1.485v3.526h0.222C344.76,45.158,345.058,45.406,345.058,46.348"/>
<path fill="#403F41" d="M427.837,42.091v-6.054h14.306v4.764c0,0.99-0.532,1.29-1.607,1.29H427.837z M427.837,27.947
c0-1.044,0.538-1.293,1.56-1.293h11.139c1.075,0,1.607,0.249,1.607,1.293v4.765h-14.306V27.947z M441.362,45.366
c3.019,0,4.329-1.091,4.329-3.918V27.102c0-2.779-1.312-3.871-4.28-3.871h-12.843c-2.965,0-4.275,1.092-4.275,3.871v35.491v1.591
c0,0,0.191,2.088,2.684,1.209l0.861-3.742V45.366H441.362z"/>
<path fill="#403F41" d="M508.855,26.306h-19.637c-0.968,0-1.754-0.783-1.754-1.755c0-0.971,0.786-1.754,1.754-1.754h19.637
c0.967,0,1.754,0.783,1.754,1.754C510.609,25.522,509.822,26.306,508.855,26.306"/>
<path fill="#403F41" d="M471.552,32.466c-0.526,0-1.048-0.235-1.395-0.688c-0.59-0.772-0.441-1.87,0.324-2.457l9.177-7.032
c0.771-0.587,1.871-0.441,2.463,0.327c0.588,0.768,0.44,1.871-0.327,2.459l-9.18,7.03C472.299,32.35,471.923,32.466,471.552,32.466"
/>
<path fill="#403F41" d="M471.552,44.823c-0.526,0-1.048-0.237-1.395-0.688c-0.59-0.771-0.441-1.871,0.324-2.46l9.177-7.028
c0.771-0.59,1.871-0.445,2.463,0.325c0.588,0.769,0.44,1.873-0.327,2.459l-9.18,7.031C472.299,44.706,471.923,44.823,471.552,44.823
"/>
<path fill="#403F41" d="M437.561,56.035c-0.539,0-1.065-0.244-1.414-0.706c-0.575-0.776-0.416-1.876,0.362-2.453l7.636-5.696
c0.778-0.58,1.877-0.42,2.459,0.357c0.574,0.775,0.416,1.873-0.359,2.454l-7.641,5.692C438.29,55.921,437.922,56.035,437.561,56.035
"/>
<path fill="#403F41" d="M511.503,39.322h-24.931c-0.97,0-1.755-0.785-1.755-1.753c0-0.97,0.785-1.757,1.755-1.757h24.931
c0.966,0,1.755,0.787,1.755,1.757C513.258,38.537,512.469,39.322,511.503,39.322"/>
<path fill="#403F41" d="M501.119,37.795v22.693c0,1.07-0.244,1.609-1.291,1.609h-2.946v3.541h3.793c2.777,0,3.872-1.308,3.872-4.271
V37.795H501.119z"/>
<path fill="#403F41" d="M496.763,65.627h-5.704c-0.972,0-1.756-0.782-1.756-1.752s0.784-1.757,1.756-1.757h5.704
c0.968,0,1.753,0.787,1.753,1.757S497.73,65.627,496.763,65.627"/>
<path fill="#403F41" d="M477.464,65.753c-0.968,0-1.757-0.784-1.757-1.754V38.671c0-0.966,0.789-1.755,1.757-1.755
c0.969,0,1.751,0.789,1.751,1.755v25.328C479.215,64.969,478.433,65.753,477.464,65.753"/>
<path fill="#403F41" d="M421.278,63.766l-15.582,1.957c-0.907,0.113-1.732-0.529-1.848-1.436s0.525-1.734,1.436-1.85l15.582-1.957
c0.903-0.113,1.734,0.527,1.849,1.437C422.826,62.823,422.184,63.648,421.278,63.766"/>
<path fill="#403F41" d="M419.811,45.484h-13.059c-0.913,0-1.655-0.742-1.655-1.656s0.742-1.655,1.655-1.655h13.059
c0.912,0,1.65,0.741,1.65,1.655S420.723,45.484,419.811,45.484"/>
<path fill="#403F41" d="M419.811,36.037h-13.059c-0.913,0-1.655-0.741-1.655-1.654c0-0.915,0.742-1.656,1.655-1.656h13.059
c0.912,0,1.65,0.741,1.65,1.656C421.461,35.296,420.723,36.037,419.811,36.037"/>
<path fill="#403F41" d="M413.28,63.768c-0.913,0-1.656-0.74-1.656-1.653V36.037c0-0.916,0.743-1.658,1.656-1.658
c0.917,0,1.653,0.742,1.653,1.658v26.076C414.934,63.025,414.197,63.768,413.28,63.768"/>
<path fill="#403F41" d="M426.263,65.514c-0.747,0-1.438-0.475-1.674-1.227c-0.288-0.923,0.224-1.908,1.146-2.199l8.729-2.743
c0.924-0.288,1.91,0.224,2.198,1.147c0.289,0.921-0.221,1.908-1.146,2.197l-8.728,2.744
C426.614,65.489,426.438,65.514,426.263,65.514"/>
<path fill="#403F41" d="M446.105,65.753c-0.354,0-0.713-0.104-1.022-0.333c-10.979-7.913-12.566-20.312-12.629-20.836
c-0.116-0.962,0.569-1.834,1.532-1.947c0.966-0.118,1.833,0.568,1.949,1.531c0.016,0.113,1.502,11.418,11.197,18.41
c0.786,0.566,0.963,1.662,0.398,2.449C447.188,65.503,446.65,65.753,446.105,65.753"/>
<path fill="#403F41" d="M404.789,32.593c-0.308,0-0.621-0.082-0.905-0.251c-0.827-0.502-1.093-1.582-0.593-2.41l3.604-5.961
c0.315-0.521,0.885-0.846,1.5-0.846h9c0.604,0,1.162,0.308,1.484,0.817l3.776,5.959c0.517,0.816,0.271,1.899-0.544,2.419
c-0.821,0.521-1.9,0.277-2.42-0.54l-3.261-5.146h-7.05l-3.088,5.111C405.963,32.293,405.386,32.593,404.789,32.593"/>
<path fill="#403F41" d="M312.107,28.894H276.88c-1.025,0-1.854-0.829-1.854-1.854c0-1.021,0.828-1.851,1.854-1.851h35.227
c1.024,0,1.854,0.829,1.854,1.851C313.961,28.064,313.132,28.894,312.107,28.894"/>
<path fill="#403F41" d="M309.937,46.15H279.05c-1.022,0-1.854-0.827-1.854-1.853c0-1.022,0.83-1.854,1.854-1.854h30.887
c1.023,0,1.854,0.832,1.854,1.854C311.789,45.323,310.96,46.15,309.937,46.15"/>
<path fill="#403F41" d="M314.682,64.891h-40.373c-1.023,0-1.854-0.83-1.854-1.854s0.83-1.854,1.854-1.854h40.373
c1.021,0,1.852,0.83,1.852,1.854C316.532,64.061,315.703,64.891,314.682,64.891"/>
<path fill="#403F41" d="M294.493,64.891c-1.021,0-1.854-0.83-1.854-1.854V27.039c0-1.022,0.831-1.851,1.854-1.851
c1.023,0,1.854,0.828,1.854,1.851v35.997C296.347,64.061,295.518,64.891,294.493,64.891"/>
<path fill="#403F41" d="M360.884,30.126c-0.573,0-1.131-0.299-1.438-0.832l-2.812-4.904c-0.454-0.794-0.182-1.803,0.608-2.26
c0.795-0.454,1.808-0.178,2.262,0.611l2.812,4.905c0.454,0.794,0.179,1.806-0.613,2.26
C361.446,30.055,361.162,30.126,360.884,30.126"/>
<path fill="#403F41" d="M370.479,30.126c-0.278,0-0.562-0.071-0.823-0.22c-0.792-0.454-1.065-1.466-0.612-2.26l2.813-4.905
c0.453-0.789,1.467-1.065,2.26-0.611c0.791,0.457,1.064,1.466,0.611,2.26l-2.812,4.904
C371.608,29.827,371.052,30.126,370.479,30.126"/>
<path fill="#403F41" d="M379.415,31.009h-27.467c-0.915,0-1.654-0.737-1.654-1.654c0-0.912,0.739-1.654,1.654-1.654h27.467
c0.913,0,1.653,0.742,1.653,1.654C381.069,30.271,380.328,31.009,379.415,31.009"/>
<path fill="#403F41" d="M365.681,36.67c-0.913,0-1.654-0.74-1.654-1.654v-5.661c0-0.912,0.741-1.654,1.654-1.654
c0.915,0,1.653,0.742,1.653,1.654v5.661C367.334,35.93,366.596,36.67,365.681,36.67"/>
<path fill="#403F41" d="M346.768,34.601c-0.532,0-1.056-0.237-1.401-0.695c-3.893-5.138-4.661-5.902-5.636-6.864l-0.157-0.154
c-0.688-0.685-0.692-1.794-0.013-2.481c0.685-0.691,1.797-0.695,2.482-0.012l0.155,0.152c1.072,1.062,1.92,1.902,5.966,7.242
c0.583,0.774,0.432,1.874-0.34,2.456C347.507,34.485,347.133,34.601,346.768,34.601"/>
<path fill="#403F41" d="M345.992,45.154h-6.62c-0.967,0-1.754-0.785-1.754-1.756s0.787-1.752,1.754-1.752h6.62
c0.969,0,1.754,0.782,1.754,1.752S346.961,45.154,345.992,45.154"/>
<path fill="#403F41" d="M365.518,65.746c-3.881,0-7.581-0.077-9.937-0.307c-4.994-0.479-7.826-3.291-9.253-5.338l-5.237,4.875
c-0.711,0.664-1.821,0.621-2.479-0.084c-0.663-0.709-0.622-1.819,0.087-2.479l6.87-6.397c0.428-0.399,1.025-0.561,1.597-0.427
c0.569,0.14,1.036,0.546,1.24,1.095c0.07,0.187,1.902,4.725,7.515,5.266c6.644,0.643,24.271,0,24.461-0.006
c0.95-0.045,1.78,0.724,1.813,1.692c0.035,0.966-0.724,1.78-1.691,1.812C379.994,65.465,372.96,65.746,365.518,65.746"/>
</svg>

+ 4
- 3
app/src/App.vue Целия файл

@@ -22,14 +22,15 @@
setAuthenticated(user) {
if (user) {
localStorage.setItem('username', user.username);
localStorage.setItem('roles', user.roles);
localStorage.setItem('level', user.level);
localStorage.setItem('department', user.department);
this.$router.replace({ name: 'asset_group' });
} else {
this.logout();
}
this.$router.replace({ name: 'asset_group' });
},
logout() {
this.$axios.get('/logout').then((resp) => {
this.$axios.get('/account/logout').then((resp) => {
console.log(resp);
})
.catch(function (resp) {


+ 366
- 170
app/src/components/AssetGroup.vue Целия файл

@@ -1,201 +1,397 @@
<template>
<div class="dashboard">
<h1>歷史報表檢視</h1>
<v-card>
<v-card-title>
歷史報表 -- 共 {{reports.length}} 筆
<v-spacer></v-spacer>
<v-select
v-model="select"
:items="reportconfs"
:rules="[v => !!v || '必須要選擇一個報表']"
label="選擇報表"
required
item-text="nameId"
item-value="id"
@change="loadReport()"
></v-select>
<div class="px-1"></div>
<v-menu
v-model="menu2"
:close-on-content-click="false"
:nudge-right="40"
transition="scale-transition"
offset-y
min-width="100px"
class="mr-3"
<div>
<div>
<v-tabs
v-model='currentTab'
centered
fixed-tabs
background-color='grey lighten-4'
show-arrows
>
<v-tab
v-for='item in assertGroup'
:key='item.text'
class=' font-weight-bold'

>
<template v-slot:activator="{ on }">
<v-text-field
v-model="date"
label="選擇報表日期"
prepend-icon="mdi-calendar"
readonly
v-on="on"
@change="loadReport()"
></v-text-field>
</template>
<v-date-picker v-model="date" @input="menu2 = false;loadReport()"></v-date-picker>
</v-menu>
<div v-if="isAdmin" class="pl-4 mb-3">
<v-tooltip bottom>
<template v-slot:activator="{ on, attrs }">
<v-icon small>{{ item.text }}</v-icon>
</v-tab>
<div class="d-flex align-center">
<v-dialog
v-model='dialogNewAssertGroup'
@click:outside='close'
>
<template v-slot:activator='{ on, attrs }'>
<v-btn
color="primary"
dark
v-bind="attrs"
v-on="on"
@click="generateReport()"
v-bind='attrs'
v-on='on'
icon
>
重新產生報表
<v-icon>mdi-plus</v-icon>
</v-btn>
</template>
<span>以選定日期重新產生報表, 不會發送 Email 及 FTP</span>
</v-tooltip>
<v-card>
<v-card-title>
<span class='headline font-weight-bold'>新增資產群組</span>
</v-card-title>
<v-card-text>
<v-container>
<v-row>
<v-col
cols='12'
sm='6'
md='4'
class='d-flex'
>
<v-text-field
v-model="assertGroupDescript"
label='群組名稱'
hint='必填'
/>
</v-col>
<v-col
v-model="assertGroupTablename"
cols='12'
sm='6'
md='4'
class='d-flex'
>
<v-text-field
label='資料庫表格名稱'
hint='必填'
/>
</v-col>
</v-row>
</v-container>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn
color='blue darken-1'
text
@click='close'
>
取消
</v-btn>
<v-btn
color='blue darken-1'
text
@click='mockInsertAssertGroup'
>
新增
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</div>
</v-card-title>
<v-data-table
:headers="headers"
:items="reports"
:search="search"
>
<template v-slot:item.fileName="{ item }">
<a href="javascript:void(0)" @click="download(item.filePath)">{{item.fileName}}</a>
</template>
</v-data-table>
</v-card>
<v-snackbar
v-model="snackbar"
:color="snackbarColor"
:timeout="snackbarTimeout"
absolute
right
rounded="pill"
top
>
{{snackbarMessage}}.
</v-snackbar>
<v-tabs-items v-model='currentTab'>
<v-tab-item
v-for='cols in inventoryItems'
:key='cols.index'
>
<v-data-table
:items='cols'
:headers='headers'
hide-default-footer
>
<template v-slot:item.actions='{ item }'>
<v-dialog
v-model='dialogModify'
@click:outside='close'
>
<template v-slot:activator='{ on, attrs }'>
<v-btn
v-bind='attrs'
v-on='on'
icon
@click='log(item)'
>
<v-icon>mdi-pencil</v-icon>
</v-btn>
</template>
<v-card>
<v-card-title>
<span class='headline font-weight-bold'>修改</span>
</v-card-title>
<v-card-text>
<v-container>
<v-row>
<v-col
v-for='(val, key, index) in item'
:key='index'
cols='12'
sm='6'
md='4'
class='d-flex'
>
<v-text-field
v-if='headers[index]'
:label='headers[index].text'
v-bind:value='val'
hint='必填'
v-on:input='oninput(modifyCol, key, $event)'
/>
</v-col>
</v-row>
</v-container>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn
color='blue darken-1'
text
@click='close'
>
取消
</v-btn>
<v-btn
color='blue darken-1'
text
@click='modifyOne(item)'
>
修改
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
<v-icon
small
@click='deleteOne(item)'
>
mdi-delete
</v-icon>
</template>
<template v-slot:footer>
<div class='d-flex ma-2'>
<v-spacer/>
<v-dialog
v-model='dialogInsert'
@click:outside='close'
>
<template v-slot:activator='{ on, attrs }'>
<v-btn
v-bind='attrs'
v-on='on'
color='primary'
>
新增欄位
</v-btn>
</template>
<v-card>
<v-card-title>
<span class='headline font-weight-bold'>新增</span>
</v-card-title>
<v-card-text>
<v-container>
<v-row>
<v-col
v-for='(val, key, index) in insertCol'
:key='index'
cols='12'
sm='6'
md='4'
class='d-flex'
>
<v-text-field
v-if='headers[index]'
:label='headers[index].text'
v-bind:value='val'
hint='必填'
v-on:input='oninput(insertCol, key, $event)'
/>
</v-col>
</v-row>
</v-container>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn
color='blue darken-1'
text
@click='close'
>
取消
</v-btn>
<v-btn
color='blue darken-1'
text
@click='modifyOne(item)'
>
修改
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</div>
</template>
</v-data-table>
</v-tab-item>
</v-tabs-items>
</v-tabs>
</div>
</div>
</template>
<script>
import axios from 'axios';
export default {
name: 'AssetGroup',
data () {
name: '',
data() {
return {
search: '',
select: null,
reportconfs: [],
date: new Date().toISOString().substr(0, 10),
menu2: false,
dialogInsert: false,
dialogModify: false,
dialogNewAssertGroup: false,
// dialogSearch: false,
title: '資訊資產群組',
headers: [
{ text: '檔案名稱', value: 'fileName',},
{ text: '產生時間', value: 'fileDate' },
// { text: '產生狀態', value: 'genstate' },
// { text: 'FTP 狀態', value: 'ftpstate' },
// { text: 'Email 狀態', value: 'emailstate' },
{'text': '中文名稱', 'value': 'descript'},
{'text': '資料庫欄位名稱', 'value': 'colname'},
{'text': '型態', 'value': 'type'},
{'text': '文字框或選項', 'value': 'select'},
{'text': '順序', 'value': 'index'},
{'text': '必填', 'value': 'require'},
{'text': '', 'value': 'actions', sortable: false}
],
reports: [],
snackbar: false,
snackbarMessage: "",
snackbarColor: "blue-grey",
snackbarTimeout: 1000,
inventoryItems: [],
insertCol: {
'tablename': '',
'colname': '',
'level': null,
'descript': '',
'type': '',
'select': '',
'search': '',
'export': '',
'require': ''
},
modifyCol: {},
assertGroup: [],
currentTab: 0,
types: [],
// selectItem: {},
// searchItem: {},
assertGroupDescript: '',
assertGroupTablename: '',
}
},
created() {
this.initialize();
async mounted() {
// this.getSelectItem();
this.getTabs();
this.getTypes();
this.inventoryItems = [];
this.getInventoryItem();
},
computed: {
isAdmin() {
let roles = localStorage.getItem( 'roles');
let admin = (roles != null && roles.indexOf('ADMIN') >= 0 );
console.log("isAdmin", admin);
return admin;
}
computed: {},
watch: {
currentTab() {
// // this.getTabs();
console.log(this.assertGroup[this.currentTab].value);
this.getTypes();
this.getInventoryItem();
},
},
methods: {
initialize() {
// axios.get("/api/access/reportview/listconf", this.editedItem)
// .then((result) => {
// let json = result.data;
// this.reportconfs = json.data
// if (this.reportconfs && this.reportconfs.length > 0) {
// this.select = this.reportconfs[0].id;
// this.loadReport();
// }
// });
log(col) {
console.log(col);
},
oninput(item, key, val) {
this.$set(item, key, val);
},
loadReport() {
axios.get("/api/access/reportview/listreport/"+ this.select + "/" + this.date)
.then((result) => {
let json = result.data;
if (json.status === "OK")
this.reports = json.data;
else {
this.reports = [];
this.$root.$emit('showError', json.message);
}
getTabs() {
this.$axios.get(`/assert/assertGroups`).then((resp) => {
resp.data.data.forEach((item) => {
let header = {'text': null, 'value': null};
header.text = item.descript;
header.value = item.tablename;
this.assertGroup.push(header);
});
// this.assertGroup.push({'text': 'mdi-plus', 'value': ''});
});
},
download(file) {
axios({
url: '/api/access/reportview/download?file=' + file, //your url
method: 'GET',
responseType: 'blob', // important
}).then((response) => {
const url = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement('a');
console.log(response);
console.log(file);
file = file.replace("\\", "/");
const fileName = file.substr(file.lastIndexOf("/")+1);
link.href = url;
link.setAttribute('download', fileName); //or any other extension
document.body.appendChild(link);
link.click();
getTypes() {
const tablename = this.assertGroup[this.currentTab] ? this.assertGroup[this.currentTab].value : 'hardware';
this.$axios.get(`/assert/Types?tablename=${tablename}`).then((resp) => {
this.types = resp.data.data;
});
},
generateReport() {
let reportId = this.select;
let date = this.date;
axios({
url: '/api/access/reportview/genreport/' + reportId + "/" + date, //your url
method: 'GET',
}).then((response) => {
let json = response.data;
if (json.status === "OK") {
this.snackbarMessage = "報表在背景執行,請稍候…";
this.snackbarColor = "blue-grey";
this.snackbarTimeout = 1000,
this.snackbar = true;
setTimeout(this.checkReportStatus, 1000);
}
else {
this.snackbarMessage = "報表無法執行:" + json.message;
this.snackbarColor = "deep-orange";
this.snackbar = true;
}
getInventoryItem() {
const tablename = this.assertGroup[this.currentTab] ? this.assertGroup[this.currentTab].value : 'hardware';
this.$axios.get(`/assert/InventoryItems?tablename=${tablename}`).then((resp) => {
this.inventoryItems = resp.data.data;
});
},
checkReportStatus() {
axios({
url: '/api/access/reportview/genreport/status', //your url
method: 'GET',
}).then((response) => {
let json = response.data;
if (json.status === "OK" && json.data === true) {
this.snackbarMessage = "報表仍在背景執行,請稍候…";
this.snackbar = true;
setTimeout(this.checkReportStatus, 1000);
}
else{
this.snackbarMessage = "報表執行完畢!";
this.snackbarTimeout = 3000,
this.snackbar = true;
this.loadReport();
insertOne() {
this.insertItem.tablename = this.tablename;
this.$axios.post(`/inventory?`, this.insertItem).then(() => {
delete this.insertItem.tablename;
this.getInventories();
this.close();
}
);
},
close() {
this.dialogInsert = false;
this.dialogModify = false;
this.dialogNewAssertGroup = false;
},
isDisabled(key) {
const disabledKey = ['id'];
return disabledKey.indexOf(key) >= 0;
},
isTextField(key) {
return this.select.indexOf(key) < 0;
},
isSelect(key) {
return this.select.indexOf(key) >= 0;
},
isRequire(key) {
return this.required.indexOf(key) >= 0;
},
getSelectItem() {
this.$axios.get(`/selectItem?tablename=${this.tablename}`).then((resp) => {
this.selectItem = resp.data.data;
});
},
},
modifyOne(item) {
item.tablename = this.tablename;
this.$axios.put(`/inventory?`, item).then(() => {
this.getInventories();
this.close();
}
);
},
deleteOne(item) {
let yes = confirm('確定刪除');
if (yes) {
this.$axios.delete(`/deleteOne?tablename=${this.tablename}&&id=${item.id}`).then(() => {
this.getInventories();
alert('已刪除');
});
}
console.log(item);
},
exportFile() {
let yes = confirm('確定匯出');
if (yes) {
// this.$axios.delete(`/deleteOne?tablename=${this.tablename}&&id=${item.id}`).then(() => {
// this.getInventories();
// });

}

},
mockInsertAssertGroup() {
// this.$axios.get(`/assert/assertGroups`).then((resp) => {
// resp.data.data.forEach((item) => {
// let header = {'text': null, 'value': null};
// header.text = item.descript;
// header.value = item.tablename;
// this.assertGroup.push(header);
// });
this.assertGroup.push({'text': this.assertGroupDescript, 'value': this.assertGroupTablename});
console.log(this.assertGroup);
// });
this.close();
},

}
}
</script>

+ 114
- 35
app/src/components/Home.vue Целия файл

@@ -46,9 +46,9 @@
:to="item.route"
class="px-0 pl-5"
>
<!-- <v-list-item-action>-->
<!-- <v-icon>{{ item.icon }}</v-icon>-->
<!-- </v-list-item-action>-->
<!-- <v-list-item-action>-->
<!-- <v-icon>{{ item.icon }}</v-icon>-->
<!-- </v-list-item-action>-->
<v-list-item-content>
<v-list-item-title class="font-weight-bold subtitle-2">
{{ item.text }}
@@ -65,33 +65,80 @@
dark
dense
>
<v-app-bar-nav-icon @click.stop="drawer = !drawer" />
<v-app-bar-nav-icon @click.stop="drawer = !drawer"/>
<v-toolbar-title
style="width: 400px"
class="ml-0 pl-4"
>
<span class="hidden-sm-and-down">資訊資產管理系統</span>
</v-toolbar-title>
<v-spacer />
<v-btn
icon
large
@click="logout"
>
<v-avatar
size="32px"
item
>
<v-img
src="logo.svg"
alt="Vuetify"
/></v-avatar>
</v-btn>
<v-spacer/>
<v-menu
offset-y
origin="center center"
:nudge-bottom="10"
transition="scale-transition">
<template v-slot:activator="{on}">
<v-btn
icon
large
v-on="on"
>
<v-avatar
size="32px"
item
>
<v-btn
color="primary lighten-2"
class="white--text"
>
{{ username.slice(1) }}
</v-btn>
</v-avatar>
</v-btn>
</template>
<v-list class="pa-0">
<v-list>
<v-list-item>
<v-list-item-avatar>
<v-icon
class="blue--text"
>
mdi-account
</v-icon>
</v-list-item-avatar>

<v-list-item-content>
<v-list-item-title>{{ username }}</v-list-item-title>
</v-list-item-content>
</v-list-item>
</v-list>
<v-divider/>
<v-list-item
v-for="(item,index) in menuitems"
:key="index"
:to="!item.href ? {name: item.name} : null"
:href="item.href"
ripple="ripple"
:disabled="item.disabled"
:target="item.target"
rel="noopener"
@click="item.click"
>
<v-list-item-action v-if="item.icon">
<v-icon>{{ item.icon }}</v-icon>
</v-list-item-action>
<v-list-item-content>
<v-list-item-title>{{ item.title }}</v-list-item-title>
</v-list-item-content>
</v-list-item>
</v-list>
</v-menu>
</v-app-bar>
<v-content>
<keep-alive>
<router-view></router-view>
</keep-alive>
<keep-alive>
<router-view></router-view>
</keep-alive>
</v-content>
<v-snackbar v-model="error" top :timeout="2500">
{{ message }}
@@ -108,19 +155,51 @@

<script>
export default {
components: {
},
components: {},
props: {
source: String,
},
data: () => ({
dialog: false,
drawer: null,
error: false,
message: "",
items: [{ text: '資訊資產群組', route: '/asset_group' }],
}),
created(){
data() {
return {
dialog: false,
drawer: null,
error: false,
message: "",
items: [{'text': '全域搜尋', 'route': '/search'}, {text: '資訊資產群組', route: '/asset_group'}],
username: localStorage.getItem('username'),
this1: this,
menuitems: [
{
icon: 'mdi-exit-to-app',
href: '#',
title: '登出',
click: () => {
this.this1.logout();
},
},
],
}
},
// data: () => ({
// dialog: false,
// drawer: null,
// error: false,
// message: "",
// items: [{text: '資訊資產群組', route: '/asset_group'}],
// username: localStorage.getItem('username'),
// this1: this,
// menuitems: [
// {
// icon: 'mdi-exit-to-app',
// href: '#',
// title: '登出',
// click: () => {
// this.logout();
// },
// },
// ],
// }),
created() {
this.$root.$on('showError', (message) => {
this.error = true;
this.message = message;
@@ -128,15 +207,15 @@
},
computed: {
isAdmin() {
let roles = localStorage.getItem('roles');
return (roles != null && roles.indexOf('ADMIN') >= 0 );
let level = localStorage.getItem('level');
return (level != null && level === '0');
},
},
mounted() {
this.getRoutes();
},
methods: {
logout(){
logout() {
this.$emit("authenticated", null);
},
async getRoutes() {


+ 259
- 128
app/src/components/Inventory.vue Целия файл

@@ -9,10 +9,96 @@
inset
vertical
/>
<v-spacer />
<p v-if="mockSearch===true" class="mb-0">搜尋條件: 資產群組: H8 儲存設備</p>
<v-spacer/>
<v-btn
color="white"
class="primary mr-5"
@click="exportFile"
icon
>
<v-icon >mdi-file-export-outline</v-icon>
</v-btn>
<v-dialog
v-model="dialogSearch"
@click:outside="close"
>
<template v-slot:activator="{ on, attrs }" >
<v-btn
color="white"
class="primary mr-5"
v-bind="attrs"
v-on="on"
icon
>
<v-icon >mdi-magnify</v-icon>
</v-btn>

</template>
<v-card>
<v-card-title>
<span class="headline font-weight-bold">搜尋</span>
</v-card-title>
<v-card-text>
<v-container>
<v-row>
<v-col

v-for="(val, key, index) in insertItem"
:key="index"
cols="12"
sm="6"
md="4"
>
<div v-if="headers[index].text !== '編號'">
<v-text-field
dense
v-if="isTextField(key) && headers[index].text"
:label="headers[index].text"
:disabled="isDisabled(key)"
v-bind:value="val"
:persistent-hint="isRequire(key)"
hint="必填"
v-on:input="oninput(insertItem, key, $event)"
/>
<v-select
dense
v-if="isSelect(key) && headers[index].text"
:persistent-hint="isRequire(key)"
hint="必選"
:label="headers[index].text"
:value="val"
v-on:input="oninput(insertItem, key, $event)"
:items="selectItem[key]"
item-text="item"
item-value="item"
/>
</div>
</v-col>
</v-row>
</v-container>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn
color="blue darken-1"
text
@click="close"
>
關閉
</v-btn>
<v-btn
color="blue darken-1"
text
@click="mockSearch=true"
>
搜尋
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
<v-dialog
v-model="dialogInsert"
max-width="500px"
@click:outside="close"
>
<template v-slot:activator="{ on, attrs }">
@@ -31,64 +117,45 @@
<v-card-title>
<span class="headline font-weight-bold">新增</span>
</v-card-title>
<v-card-text>
<v-container>
<v-row>
<v-col

<!-- <v-card-text>-->
<!-- <v-container>-->
<!-- <v-row>-->
<!-- <v-col-->
<!-- cols="12"-->
<!-- sm="6"-->
<!-- md="4"-->
<!-- >-->
<!-- <v-text-field-->
<!-- v-model="editedItem.name"-->
<!-- label="Dessert name"-->
<!-- ></v-text-field>-->
<!-- </v-col>-->
<!-- <v-col-->
<!-- cols="12"-->
<!-- sm="6"-->
<!-- md="4"-->
<!-- >-->
<!-- <v-text-field-->
<!-- v-model="editedItem.calories"-->
<!-- label="Calories"-->
<!-- ></v-text-field>-->
<!-- </v-col>-->
<!-- <v-col-->
<!-- cols="12"-->
<!-- sm="6"-->
<!-- md="4"-->
<!-- >-->
<!-- <v-text-field-->
<!-- v-model="editedItem.fat"-->
<!-- label="Fat (g)"-->
<!-- ></v-text-field>-->
<!-- </v-col>-->
<!-- <v-col-->
<!-- cols="12"-->
<!-- sm="6"-->
<!-- md="4"-->
<!-- >-->
<!-- <v-text-field-->
<!-- v-model="editedItem.carbs"-->
<!-- label="Carbs (g)"-->
<!-- ></v-text-field>-->
<!-- </v-col>-->
<!-- <v-col-->
<!-- cols="12"-->
<!-- sm="6"-->
<!-- md="4"-->
<!-- >-->
<!-- <v-text-field-->
<!-- v-model="editedItem.protein"-->
<!-- label="Protein (g)"-->
<!-- ></v-text-field>-->
<!-- </v-col>-->
<!-- </v-row>-->
<!-- </v-container>-->
<!-- </v-card-text>-->

v-for="(val, key, index) in insertItem"
:key="index"
cols="12"
sm="6"
md="4"
>
<div v-if="headers[index].text !== '編號'">
<v-text-field
dense
v-if="isTextField(key) && headers[index].text"
:label="headers[index].text"
:disabled="isDisabled(key)"
v-bind:value="val"
:persistent-hint="isRequire(key)"
hint="必填"
v-on:input="oninput(insertItem, key, $event)"
/>
<v-select
dense
v-if="isSelect(key) && headers[index].text"
:persistent-hint="isRequire(key)"
hint="必選"
:label="headers[index].text"
:value="val"
v-on:input="oninput(insertItem, key, $event)"
:items="selectItem[key]"
item-text="item"
item-value="item"
/>
</div>
</v-col>
</v-row>
</v-container>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn
@@ -120,7 +187,7 @@
v-bind="attrs"
v-on="on"
icon
@click="modifyItem = item;"
@click="modifyItem = JSON.parse(JSON.stringify(item))"
>
<v-icon>mdi-pencil</v-icon>
</v-btn>
@@ -129,28 +196,42 @@
<v-card-title>
<span class="headline font-weight-bold">修改</span>
</v-card-title>
<v-card-text>
<v-container>
<v-row>
<v-col

v-for="(val, key, index) in modifyItem"
:key="index"
cols="12"
sm="6"
md="4"
class="d-flex"
>
<v-text-field
:label="headers[index].text"
v-bind:value="val"
v-on:input="oninput(key, $event)"
></v-text-field>
</v-col>
</v-row>
</v-container>
</v-card-text>
<v-card-text>
<v-container>
<v-row>
<v-col

v-for="(val, key, index) in modifyItem"
:key="index"
cols="12"
sm="6"
md="4"
class="d-flex"
>
<v-text-field
v-if="isTextField(key) && headers[index].text"
:label="headers[index].text"
:disabled="isDisabled(key)"
v-bind:value="val"
:persistent-hint="isRequire(key)"
hint="必填"
v-on:input="oninput(modifyItem, key, $event)"
/>
<v-select
v-if="isSelect(key) && headers[index].text"
:persistent-hint="isRequire(key)"
hint="必選"
:label="headers[index].text"
:value="val"
v-on:input="oninput(modifyItem, key, $event)"
:items="selectItem[key]"
item-text="item"
item-value="item"
/>
</v-col>
</v-row>
</v-container>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn
@@ -187,94 +268,144 @@
return {
dialogInsert: false,
dialogModify: false,
dialogSearch: false,
title: '',
headers: [
],
headers: [],
cols: {},
items: [],
modifyItem: {}
select: [],
required: [],
insertItem: {},
modifyItem: {},
selectItem: {},
searchItem: {},
mockSearch: false,
}
},
mounted() {
async mounted() {
this.getHeaders();
this.getInventories();
console.log(this.$route.params.tablename);
this.getTitle();
this.getSelectItem();
},
computed: {
tablename() {
return this.$route.params.tablename;
}
},
watch: {
tablename() {
this.headers = [];
this.headers = [];
this.getHeaders();
this.items = [];
this.getInventories();
this.title = '';
this.getTitle();
return this.$route.params.tablename;
},
modifyItem() {
// this.modifyItem.sort
console.log(this.modifyItem);
},
watch: {
async tablename() {
if (this.$route.params.tablename) {
this.headers = [];
this.items = [];
this.title = '';
this.selectItem = {};
this.insertItem = {};
this.getHeaders();
this.getInventories();
this.getTitle();
this.getSelectItem();
}
},
},
methods: {
log() {
alert('as');
},
oninput(key, val) {
console.log(val);
this.$set(this.modifyItem, key, val);
console.log(this.modifyItem);

oninput(item, key, val) {
this.$set(item, key, val);
},
async getTitle() {
this.$axios.get(`/title?tablename=${this.tablename}`).then((resp) => {
this.title = `${resp.data.data}類`;
});
getTitle() {
this.$axios.get(`/title?tablename=${this.tablename}`).then((resp) => {
this.title = `${resp.data.data}類`;
});
},
async getHeaders() {
getHeaders() {
this.$axios.get(`/headers?tablename=${this.tablename}`).then((resp) => {
this.cols = resp.data.data;
resp.data.data.forEach((item) => {
let header = {};
header.text = item.descript;
header.value = item.colname;
this.headers.push(header);
let header = {'text': null, 'value': null};
header.text = item.descript;
header.value = item.colname;
this.headers.push(header);
if (item.select === 'true') {
this.select.push(item.colname);
}
if (item.require === 'true') {
this.required.push(item.colname);
}
this.insertItem[item.colname] = null;
this.searchItem[item.colname] = null;
});
this.headers.push({text: '', value: 'actions', sortable: false});
this.headers.push({'text': '', 'value': 'actions', sortable: false});
});
},
async getInventories() {
getInventories() {
this.$axios.get(`/inventory?tablename=${this.tablename}`).then((resp) => {
console.log(resp);
this.items = resp.data.data;
});
},
async insertOne(item, prop) {
console.log(item);
console.log(prop);
insertOne() {
this.insertItem.tablename = this.tablename;
this.$axios.post(`/inventory?`, this.insertItem).then(() => {
delete this.insertItem.tablename;
this.getInventories();
this.close();
}
);
},
async close() {
close() {
this.dialogInsert = false;
this.dialogModify = false;
this.dialogSearch = false;
},
async modifyOne(item) {
isDisabled(key) {
const disabledKey = ['id'];
return disabledKey.indexOf(key) >= 0;
},
isTextField(key) {
return this.select.indexOf(key) < 0;
},
isSelect(key) {
return this.select.indexOf(key) >= 0;
},
isRequire(key) {
return this.required.indexOf(key) >= 0;
},
getSelectItem() {
this.$axios.get(`/selectItem?tablename=${this.tablename}`).then((resp) => {
this.selectItem = resp.data.data;
});
},
modifyOne(item) {
item.tablename = this.tablename;
console.log(item);
this.$axios.put(`/inventory?`, item).then(() => {
this.getInventories();
this.close();
this.getInventories();
this.close();
}
);
},
async deleteOne(item) {
deleteOne(item) {
let yes = confirm('確定刪除');
if (yes) {
alert('已刪除');
this.$axios.delete(`/deleteOne?tablename=${this.tablename}&&id=${item.id}`).then(() => {
this.getInventories();
alert('已刪除');
});
}
console.log(item);
},
exportFile() {
let yes = confirm('確定匯出');
if (yes) {
// this.$axios.delete(`/deleteOne?tablename=${this.tablename}&&id=${item.id}`).then(() => {
// this.getInventories();
// });

}

}

}
}
</script>

+ 20
- 16
app/src/components/Login.vue Целия файл

@@ -1,19 +1,26 @@
<template>
<v-main>
<v-container
class='fill-height'
class='fill-height primary lighten-3 d-flex'
fluid
>
<v-row
align='center'
justify='center'
class="mb-10"
no-gutters
>
<v-col cols="12" align-self="center" class="d-flex">
<v-spacer/>
<img src="obank_logo.svg">
<v-spacer/>
</v-col>
<v-col
cols='12'
sm='8'
md='4'
>
<v-card class='elevation-12'>
<v-card class='elevation-12 grey lighten-3'>
<v-toolbar
color='primary'
dark
@@ -25,7 +32,7 @@
<v-card-text>
<v-form>
<v-text-field
v-model='input.username'
v-model='input.account'
label='Login'
name='login'
prepend-icon='mdi-account'
@@ -44,7 +51,7 @@
</v-card-text>
<v-card-actions>
<v-spacer />
<v-btn color='primary' v-on:click='logintest()'>Login</v-btn>
<v-btn color='primary' v-on:click='login()'>登入</v-btn>
</v-card-actions>
</v-card>
</v-col>
@@ -68,7 +75,7 @@
data() {
return {
input: {
username: '',
account: '',
password: '',
},
loginError : false,
@@ -81,28 +88,25 @@
this.$emit('authenticated',
{
'username':'aaa',
'roles': 'aaa',
'department': 'aaa',
'level': '1'
});
},
login() {
this.loginError = false;
const _this = this;
if(this.input.username !== '' && this.input.password !== '') {
const bodyFormData = new FormData();
bodyFormData.set('username', this.input.username);
bodyFormData.set('password', this.input.password);
this.$axios.post('/login', this.input).then((resp) => {
this.$axios.post('/account/login', this.input).then((resp) => {
if (resp.status === 200) {
//成功
const json = resp.data;
if (json.status === 'OK') {

if (json.code === 200) {
_this.$emit('authenticated',
{
'username': _this.input.username,
'roles': json.data
'username': json.data.username,
'department': json.data.department,
'level': json.data.level
});
_this.$router.replace({ name: 'report_view' });
_this.$router.replace({ name: 'asset_group' });
} else {
_this.message = json.message;
_this.loginError = true;


+ 220
- 0
app/src/components/MockSearch.vue Целия файл

@@ -0,0 +1,220 @@
<template>
<div>
<div>
<v-row justify="center" dense class="mt-1">
<v-col cols="4">
<v-text-field outlined rounded>
<template v-slot:append>
<v-icon @click="show = true">mdi-magnify</v-icon>
</template>
</v-text-field>
</v-col>
</v-row>
<v-toolbar flat v-if="show === true">
<v-toolbar-title>搜尋結果</v-toolbar-title>
<v-tabs
v-model='currentTab'
centered
show-arrows
style="width: 80%"
>
<v-tab
v-for='item in assertGroup'
:key='item.text'
class=' font-weight-bold'

>
<v-icon small>{{ item.text }}</v-icon>
</v-tab>

<v-tabs-items v-model='currentTab'>
<v-tab-item
v-for='cols in inventoryItems'
:key='cols.index'
>
<v-data-table
:items='cols'
:headers='headers'
hide-default-footer
>
</v-data-table>
</v-tab-item>
</v-tabs-items>
</v-tabs>
<v-btn
color="white"
class="primary mr-5"
@click="exportFile"
icon
>
<v-icon >mdi-file-export-outline</v-icon>
</v-btn>
</v-toolbar>
</div>
</div>
</template>
<script>
export default {
name: '',
data() {
return {
dialogInsert: false,
dialogModify: false,
dialogNewAssertGroup: false,
// dialogSearch: false,
title: '資訊資產群組',
headers: [
{'text': '中文名稱', 'value': 'descript'},
{'text': '資料庫欄位名稱', 'value': 'colname'},
{'text': '型態', 'value': 'type'},
{'text': '文字框或選項', 'value': 'select'},
{'text': '順序', 'value': 'index'},
{'text': '必填', 'value': 'require'},
{'text': '', 'value': 'actions', sortable: false}
],
inventoryItems: [],
insertCol: {
'tablename': '',
'colname': '',
'level': null,
'descript': '',
'type': '',
'select': '',
'search': '',
'export': '',
'require': ''
},
modifyCol: {},
assertGroup: [],
currentTab: 0,
types: [],
// selectItem: {},
// searchItem: {},
assertGroupDescript: '',
assertGroupTablename: '',
show: false,
}
},
async mounted() {
// this.getSelectItem();
this.getTabs();
this.getTypes();
this.inventoryItems = [];
this.getInventoryItem();
},
computed: {},
watch: {
currentTab() {
// // this.getTabs();
console.log(this.assertGroup[this.currentTab].value);
this.getTypes();
this.getInventoryItem();
},
},
methods: {
log(col) {
console.log(col);
},
oninput(item, key, val) {
this.$set(item, key, val);
},
getTabs() {
this.$axios.get(`/assert/assertGroups`).then((resp) => {
resp.data.data.forEach((item) => {
let header = {'text': null, 'value': null};
header.text = item.descript;
header.value = item.tablename;
this.assertGroup.push(header);
});
// this.assertGroup.push({'text': 'mdi-plus', 'value': ''});
});
},
getTypes() {
const tablename = this.assertGroup[this.currentTab] ? this.assertGroup[this.currentTab].value : 'hardware';
this.$axios.get(`/assert/Types?tablename=${tablename}`).then((resp) => {
this.types = resp.data.data;
});
},
getInventoryItem() {
const tablename = this.assertGroup[this.currentTab] ? this.assertGroup[this.currentTab].value : 'hardware';
this.$axios.get(`/assert/InventoryItems?tablename=${tablename}`).then((resp) => {
this.inventoryItems = resp.data.data;
});
},
insertOne() {
this.insertItem.tablename = this.tablename;
this.$axios.post(`/inventory?`, this.insertItem).then(() => {
delete this.insertItem.tablename;
this.getInventories();
this.close();
}
);
},
close() {
this.dialogInsert = false;
this.dialogModify = false;
this.dialogNewAssertGroup = false;
},
isDisabled(key) {
const disabledKey = ['id'];
return disabledKey.indexOf(key) >= 0;
},
isTextField(key) {
return this.select.indexOf(key) < 0;
},
isSelect(key) {
return this.select.indexOf(key) >= 0;
},
isRequire(key) {
return this.required.indexOf(key) >= 0;
},
getSelectItem() {
this.$axios.get(`/selectItem?tablename=${this.tablename}`).then((resp) => {
this.selectItem = resp.data.data;
});
},
modifyOne(item) {
item.tablename = this.tablename;
this.$axios.put(`/inventory?`, item).then(() => {
this.getInventories();
this.close();
}
);
},
deleteOne(item) {
let yes = confirm('確定刪除');
if (yes) {
this.$axios.delete(`/deleteOne?tablename=${this.tablename}&&id=${item.id}`).then(() => {
this.getInventories();
alert('已刪除');
});
}
console.log(item);
},
exportFile() {
let yes = confirm('確定匯出');
if (yes) {
// this.$axios.delete(`/deleteOne?tablename=${this.tablename}&&id=${item.id}`).then(() => {
// this.getInventories();
// });

}

},
mockInsertAssertGroup() {
// this.$axios.get(`/assert/assertGroups`).then((resp) => {
// resp.data.data.forEach((item) => {
// let header = {'text': null, 'value': null};
// header.text = item.descript;
// header.value = item.tablename;
// this.assertGroup.push(header);
// });
this.assertGroup.push({'text': this.assertGroupDescript, 'value': this.assertGroupTablename});
console.log(this.assertGroup);
// });
this.close();
},

}
}
</script>

+ 178
- 0
app/src/components/Search.vue Целия файл

@@ -0,0 +1,178 @@
<template>
<v-container fluid>
<v-row justify="center" dense class="mt-1">
<v-col cols="4">
<v-text-field outlined prepend-inner-icon="mdi-magnify" rounded />
</v-col>
</v-row>
<v-data-table class="pa-3 pt-5" :headers="headers" :items="items">
<template v-slot:top>
<v-toolbar flat>
<v-toolbar-title class="title font-weight-bold">搜尋結果</v-toolbar-title>
<v-divider
class="mx-4"
inset
vertical
/>
<v-spacer/>
<v-btn
color="white"
class="primary mr-5"
@click="exportFile"
icon
>
<v-icon >mdi-file-export-outline</v-icon>
</v-btn>
</v-toolbar>
</template>
</v-data-table>

</v-container>
</template>
<script>
export default {
name: '',
data() {
return {
dialogInsert: false,
dialogModify: false,
dialogSearch: false,
title: '',
headers: [],
cols: {},
items: [],
select: [],
required: [],
insertItem: {},
modifyItem: {},
selectItem: {},
searchItem: {},
}
},
async mounted() {
this.getHeaders();
this.getInventories();
this.getTitle();
this.getSelectItem();
},
computed: {
tablename() {
return 'hardware';
},
},
watch: {
async tablename() {
if (this.$route.params.tablename) {
this.headers = [];
this.items = [];
this.title = '';
this.selectItem = {};
this.insertItem = {};
this.getHeaders();
this.getInventories();
this.getTitle();
this.getSelectItem();
}
},
},
methods: {
log() {
alert('as');
},
oninput(item, key, val) {
this.$set(item, key, val);
},
getTitle() {
this.$axios.get(`/title?tablename=${this.tablename}`).then((resp) => {
this.title = `${resp.data.data}類`;
});
},
getHeaders() {
this.$axios.get(`/headers?tablename=${this.tablename}`).then((resp) => {
this.cols = resp.data.data;
resp.data.data.forEach((item) => {
let header = {'text': null, 'value': null};
header.text = item.descript;
header.value = item.colname;
this.headers.push(header);
if (item.select === 'true') {
this.select.push(item.colname);
}
if (item.require === 'true') {
this.required.push(item.colname);
}
this.insertItem[item.colname] = null;
this.searchItem[item.colname] = null;
});
this.headers.push({'text': '', 'value': 'actions', sortable: false});
});
},
getInventories() {
this.$axios.get(`/inventory?tablename=${this.tablename}`).then((resp) => {
this.items = resp.data.data;
});
},
insertOne() {
this.insertItem.tablename = this.tablename;
this.$axios.post(`/inventory?`, this.insertItem).then(() => {
delete this.insertItem.tablename;
this.getInventories();
this.close();
}
);
},
close() {
this.dialogInsert = false;
this.dialogModify = false;
this.dialogSearch = false;
},
isDisabled(key) {
const disabledKey = ['id'];
return disabledKey.indexOf(key) >= 0;
},
isTextField(key) {
return this.select.indexOf(key) < 0;
},
isSelect(key) {
return this.select.indexOf(key) >= 0;
},
isRequire(key) {
return this.required.indexOf(key) >= 0;
},
getSelectItem() {
this.$axios.get(`/selectItem?tablename=${this.tablename}`).then((resp) => {
this.selectItem = resp.data.data;
});
},
modifyOne(item) {
item.tablename = this.tablename;
this.$axios.put(`/inventory?`, item).then(() => {
this.getInventories();
this.close();
}
);
},
deleteOne(item) {
let yes = confirm('確定刪除');
if (yes) {
this.$axios.delete(`/deleteOne?tablename=${this.tablename}&&id=${item.id}`).then(() => {
this.getInventories();
alert('已刪除');
});
}
console.log(item);
},
exportFile() {
let yes = confirm('確定匯出');
if (yes) {
// this.$axios.delete(`/deleteOne?tablename=${this.tablename}&&id=${item.id}`).then(() => {
// this.getInventories();
// });

}

}

}
}
</script>

+ 201
- 0
app/src/components/xxx.vue Целия файл

@@ -0,0 +1,201 @@
<template>
<div class="dashboard">
<h1>歷史報表檢視</h1>
<v-card>
<v-card-title>
歷史報表 -- 共 {{reports.length}} 筆
<v-spacer></v-spacer>
<v-select
v-model="select"
:items="reportconfs"
:rules="[v => !!v || '必須要選擇一個報表']"
label="選擇報表"
required
item-text="nameId"
item-value="id"
@change="loadReport()"
></v-select>
<div class="px-1"></div>
<v-menu
v-model="menu2"
:close-on-content-click="false"
:nudge-right="40"
transition="scale-transition"
offset-y
min-width="100px"
class="mr-3"
>
<template v-slot:activator="{ on }">
<v-text-field
v-model="date"
label="選擇報表日期"
prepend-icon="mdi-calendar"
readonly
v-on="on"
@change="loadReport()"
></v-text-field>
</template>
<v-date-picker v-model="date" @input="menu2 = false;loadReport()"></v-date-picker>
</v-menu>
<div v-if="isAdmin" class="pl-4 mb-3">
<v-tooltip bottom>
<template v-slot:activator="{ on, attrs }">
<v-btn
color="primary"
dark
v-bind="attrs"
v-on="on"
@click="generateReport()"
>
重新產生報表
</v-btn>
</template>
<span>以選定日期重新產生報表, 不會發送 Email 及 FTP</span>
</v-tooltip>
</div>
</v-card-title>
<v-data-table
:headers="headers"
:items="reports"
:search="search"
>
<template v-slot:item.fileName="{ item }">
<a href="javascript:void(0)" @click="download(item.filePath)">{{item.fileName}}</a>
</template>
</v-data-table>
</v-card>
<v-snackbar
v-model="snackbar"
:color="snackbarColor"
:timeout="snackbarTimeout"
absolute
right
rounded="pill"
top
>
{{snackbarMessage}}.
</v-snackbar>
</div>
</template>
<script>
import axios from 'axios';
export default {
name: 'AssetGroup',
data () {
return {
search: '',
select: null,
reportconfs: [],
date: new Date().toISOString().substr(0, 10),
menu2: false,
headers: [
{ text: '檔案名稱', value: 'fileName',},
{ text: '產生時間', value: 'fileDate' },
// { text: '產生狀態', value: 'genstate' },
// { text: 'FTP 狀態', value: 'ftpstate' },
// { text: 'Email 狀態', value: 'emailstate' },
],
reports: [],
snackbar: false,
snackbarMessage: "",
snackbarColor: "blue-grey",
snackbarTimeout: 1000,
}
},
created() {
this.initialize();
},
computed: {
isAdmin() {
let roles = localStorage.getItem( 'roles');
let admin = (roles != null && roles.indexOf('ADMIN') >= 0 );
console.log("isAdmin", admin);
return admin;
}
},
methods: {
initialize() {
// axios.get("/api/access/reportview/listconf", this.editedItem)
// .then((result) => {
// let json = result.data;
// this.reportconfs = json.data
// if (this.reportconfs && this.reportconfs.length > 0) {
// this.select = this.reportconfs[0].id;
// this.loadReport();
// }
// });
},
loadReport() {
axios.get("/api/access/reportview/listreport/"+ this.select + "/" + this.date)
.then((result) => {
let json = result.data;
if (json.status === "OK")
this.reports = json.data;
else {
this.reports = [];
this.$root.$emit('showError', json.message);
}
});
},
download(file) {
axios({
url: '/api/access/reportview/download?file=' + file, //your url
method: 'GET',
responseType: 'blob', // important
}).then((response) => {
const url = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement('a');
console.log(response);
console.log(file);
file = file.replace("\\", "/");
const fileName = file.substr(file.lastIndexOf("/")+1);
link.href = url;
link.setAttribute('download', fileName); //or any other extension
document.body.appendChild(link);
link.click();
});
},
generateReport() {
let reportId = this.select;
let date = this.date;
axios({
url: '/api/access/reportview/genreport/' + reportId + "/" + date, //your url
method: 'GET',
}).then((response) => {
let json = response.data;
if (json.status === "OK") {
this.snackbarMessage = "報表在背景執行,請稍候…";
this.snackbarColor = "blue-grey";
this.snackbarTimeout = 1000,
this.snackbar = true;
setTimeout(this.checkReportStatus, 1000);
}
else {
this.snackbarMessage = "報表無法執行:" + json.message;
this.snackbarColor = "deep-orange";
this.snackbar = true;
}
});
},
checkReportStatus() {
axios({
url: '/api/access/reportview/genreport/status', //your url
method: 'GET',
}).then((response) => {
let json = response.data;
if (json.status === "OK" && json.data === true) {
this.snackbarMessage = "報表仍在背景執行,請稍候…";
this.snackbar = true;
setTimeout(this.checkReportStatus, 1000);
}
else{
this.snackbarMessage = "報表執行完畢!";
this.snackbarTimeout = 3000,
this.snackbar = true;
this.loadReport();
}
});
},
},
}
</script>

+ 10
- 3
app/src/router/index.js Целия файл

@@ -4,6 +4,8 @@ import Login from '@/components/Login'
import Home from '../components/Home';
import AssetGroup from '../components/AssetGroup';
import Inventory from '../components/Inventory';
// import Search from '../components/Search';
import MockSearch from '../components/MockSearch';

Vue.use(Router);

@@ -14,20 +16,25 @@ export const constantRoutes = [
component: Login,
},
{
path: '/home',
path: '/',
component: Home,
name: 'home',
children: [
{
path: '/asset_group',
path: 'asset_group',
name: 'asset_group',
component: AssetGroup
},
{
path: '/inventory/:tablename',
path: 'inventory/:tablename',
name: 'inventory',
component: Inventory
},
{
path: 'search',
name: 'search',
component: MockSearch
},
]
}
];


+ 13
- 3
src/main/java/com/moze/rms/config/JdbiFactory.java Целия файл

@@ -1,8 +1,6 @@
package com.moze.rms.config;

import com.moze.rms.dao.InventoryDAO;
import com.moze.rms.dao.MappingColDAO;
import com.moze.rms.dao.MappingTableDAO;
import com.moze.rms.dao.*;
import org.jdbi.v3.core.Jdbi;
import org.jdbi.v3.core.statement.SqlLogger;
import org.jdbi.v3.core.statement.StatementContext;
@@ -66,4 +64,16 @@ public class JdbiFactory {
public InventoryDAO inventoryDAO(Jdbi jdbi) {
return jdbi.onDemand(InventoryDAO.class);
}

@Bean
public AccountDAO accountDAO(Jdbi jdbi) {
return jdbi.onDemand(AccountDAO.class);
}

@Bean
public AssertDAO assertDAO(Jdbi jdbi) {
return jdbi.onDemand(AssertDAO.class);
}


}

+ 23
- 2
src/main/java/com/moze/rms/controller/AccountController.java Целия файл

@@ -1,10 +1,31 @@
package com.moze.rms.controller;


import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.moze.rms.dao.AccountDAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.Map;

@RestController
@RequestMapping("/api/account")
public class AccountController {

@Autowired
AccountDAO accountDAO;

@PostMapping("/login")
public JsonResult login(@RequestBody Map<String, String> data) {
Map<String, Object> user = accountDAO.findUser(data.get("account"));
if (user.get("pwd").equals(data.get("password"))) {
return new JsonResult(StatusCode.SUCCESS, user);
} else {
return new JsonResult(StatusCode.NOT_LOGIN, null);
}
}

@PostMapping("/logout")
public JsonResult logout() {
return new JsonResult(StatusCode.SUCCESS, null);
}
}

+ 45
- 0
src/main/java/com/moze/rms/controller/AssertGroupController.java Целия файл

@@ -0,0 +1,45 @@
package com.moze.rms.controller;

import com.moze.rms.dao.AssertDAO;
import com.moze.rms.entity.dto.SelectItemDTO;
import com.moze.rms.entity.model.MappingCol;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/api/assert")
public class AssertGroupController {

@Autowired
AssertDAO assertDAO;


@GetMapping("/assertGroups")
public JsonResult getAsserts() {

return new JsonResult(StatusCode.SUCCESS, assertDAO.findAssertGroups());

}

@GetMapping("/Types")
public JsonResult getTypesByTable(@RequestParam String tablename) {
return new JsonResult(StatusCode.SUCCESS, assertDAO.findTypesByTable(tablename));
}

@GetMapping("/InventoryItems")
public JsonResult getInventoryItems(@RequestParam String tablename) {

// return new JsonResult(StatusCode.SUCCESS, data.stream().collect(Collectors.groupingBy(SelectItemDTO::getColname)));
List<MappingCol> data = assertDAO.findInventoryItems();

return new JsonResult(StatusCode.SUCCESS, data.stream().collect(Collectors.groupingBy(MappingCol::getTablename)));
}
}


+ 24
- 2
src/main/java/com/moze/rms/controller/InventoryController.java Целия файл

@@ -4,10 +4,13 @@ package com.moze.rms.controller;
import com.moze.rms.dao.InventoryDAO;
import com.moze.rms.dao.MappingColDAO;
import com.moze.rms.dao.MappingTableDAO;
import com.moze.rms.entity.dto.SelectItemDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.Map;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/api")
@@ -38,7 +41,6 @@ public class InventoryController {

@GetMapping("/headers")
public JsonResult getHeaders(@RequestParam String tablename) {

return new JsonResult(StatusCode.SUCCESS, mappingColDAO.findByTable(tablename));
}
@GetMapping("/inventory")
@@ -46,6 +48,13 @@ public class InventoryController {
return new JsonResult(StatusCode.SUCCESS, inventoryDAO.getInventoryByTablename(tablename));
}

@PostMapping("/inventory")
public JsonResult insertInventory(@RequestBody Map<String, Object> data) {
System.out.println(data);
inventoryDAO.insertOne(data);
return new JsonResult(StatusCode.SUCCESS, null);
}

@PutMapping("/inventory")
public JsonResult modifyInventory(@RequestBody Map<String, Object> data) {
try {
@@ -56,5 +65,18 @@ public class InventoryController {
}

}
@GetMapping("/selectItem")
public JsonResult getSelectItem(@RequestParam String tablename) {

List<SelectItemDTO> data = inventoryDAO.getSelectItemByTable(tablename);
return new JsonResult(StatusCode.SUCCESS, data.stream().collect(Collectors.groupingBy(SelectItemDTO::getColname)));
}
@DeleteMapping("deleteOne")
public JsonResult deleteOne(@RequestParam String tablename, @RequestParam String id) {
System.out.println(tablename);
System.out.println(id);
inventoryDAO.deleteByTablenameAndId(tablename, id);
return new JsonResult(StatusCode.SUCCESS, null);
}

}

+ 18
- 0
src/main/java/com/moze/rms/dao/AccountDAO.java Целия файл

@@ -0,0 +1,18 @@
package com.moze.rms.dao;

import org.jdbi.v3.core.Handle;
import org.jdbi.v3.sqlobject.SqlObject;
import org.jdbi.v3.sqlobject.config.RegisterBeanMapper;
import org.jdbi.v3.sqlobject.statement.SqlQuery;

import java.util.Map;

public interface AccountDAO extends SqlObject {

@RegisterBeanMapper(Object.class)
default Map<String, Object> findUser(String account) {
Handle handle = this.getHandle();
String sql = "select * from account where account = '" + account + "'";
return handle.createQuery(sql).mapToMap().one();
}
}

+ 49
- 0
src/main/java/com/moze/rms/dao/AssertDAO.java Целия файл

@@ -0,0 +1,49 @@
package com.moze.rms.dao;


import com.moze.rms.entity.model.MappingCol;
import org.jdbi.v3.core.Handle;
import org.jdbi.v3.sqlobject.SqlObject;
import org.jdbi.v3.sqlobject.config.RegisterBeanMapper;
import org.jdbi.v3.sqlobject.statement.SqlQuery;

import java.util.List;
import java.util.Map;

public interface AssertDAO extends SqlObject {

@RegisterBeanMapper(Object.class)
default List<Map<String, Object>> findAssertGroups() {
Handle handle = this.getHandle();
String sql = "select * from mapping.mapping_table;";
return handle.createQuery(sql).mapToMap().list();
}


default List<Map<String, Object>> findTypesByTable(String tablename) {
List<Map<String, Object>> assertGroup = findAssertGroups();

Handle handle = this.getHandle();
// String sql = "select * from mapping.mapping_" + assertGroup.get(0).get("tablename");
// for (int i = 1; i <= assertGroup.size() - 1; i++) {
// sql += " union select * from mapping.mapping_" + assertGroup.get(i).get("tablename");
// }
// String sql = "select * from mapping.\"selectItem\" where tablename = '" + tablename + "' and colname = 'type' order by index;";
String sql = "select * from mapping.mapping_" + tablename + " order by type";
return handle.createQuery(sql).mapToMap().list();
}


// default List<Map<String, Object>> findInventoryItemByTable() {
// List<Map<String, Object>> assertGroup = findAssertGroups();
//
// Handle handle = this.getHandle();
//// String sql = "select * from mapping.mapping_col where tablename = '" + tablename + "' order by index;";
// String sql = "select * from mapping.mapping_col;";
// return handle.createQuery(sql).mapToMap().list();
// }

@RegisterBeanMapper(MappingCol.class)
@SqlQuery("select * from mapping.mapping_col")
List<MappingCol> findInventoryItems();
}

+ 43
- 3
src/main/java/com/moze/rms/dao/InventoryDAO.java Целия файл

@@ -1,12 +1,14 @@
package com.moze.rms.dao;


import com.moze.rms.entity.dto.SelectItemDTO;
import org.jdbi.v3.core.Handle;
import org.jdbi.v3.sqlobject.SqlObject;
import org.jdbi.v3.sqlobject.config.RegisterBeanMapper;
import org.jdbi.v3.sqlobject.statement.SqlQuery;
import org.jdbi.v3.sqlobject.statement.SqlUpdate;

import java.util.Iterator;
import java.util.List;
import java.util.Map;

@@ -26,10 +28,48 @@ public interface InventoryDAO extends SqlObject {
String sql = "update " + data.get("tablename") + " set ";
for (Map.Entry<String, Object> entry : data.entrySet()) {
if (!entry.getKey().equals("id") && !entry.getKey().equals("tablename"))
sql += entry.getKey() + " = " + entry.getValue() + ",";
if (entry.getValue() != null) {
sql += entry.getKey() + " = '" + entry.getValue() + "',";
} else {
sql += entry.getKey() + " = " + entry.getValue() + ",";
}
}
sql = sql.substring(0, sql.length()-1);
sql += "where id = " + data.get("id");
sql = sql.substring(0, sql.length() - 1);
sql += " where id = '" + data.get("id") + "'";
handle.createUpdate(sql).execute();
}

@SqlQuery("select colname, item from mapping.\"selectItem\" where tablename = ? order by index;")
@RegisterBeanMapper(SelectItemDTO.class)
List<SelectItemDTO> getSelectItemByTable(String tablename);

default void deleteByTablenameAndId(String tablename, String id) {

Handle handle = this.getHandle();
String sql = "delete from " + tablename + " where id = " + id;
handle.execute(sql);
}

default void insertOne(Map<String, Object> data) {
Iterator<Map.Entry<String, Object>> iterator = data.entrySet().iterator();
String cols = "";
String values = "";
while (iterator.hasNext()) {
Map.Entry<String, Object> next = iterator.next();
String key = next.getKey();
Object value = next.getValue();
System.out.println(key);
if (key != "tablename" && key != "id") {
cols += key + ", ";
values += "'" + value + "', ";
}
}
cols = cols.substring(0, cols.length() - 2);
values = values.substring(0, values.length() - 2);

Handle handle = this.getHandle();
String sql = "insert into " + data.get("tablename") + " ( " + cols + " ) " + " values ( " + values + " ) ";
handle.execute(sql);
}

}

+ 12
- 0
src/main/java/com/moze/rms/entity/dto/SelectItemDTO.java Целия файл

@@ -0,0 +1,12 @@
package com.moze.rms.entity.dto;

import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
public class SelectItemDTO {

private String colname;
private String item;
}

+ 4
- 0
src/main/java/com/moze/rms/entity/model/MappingCol.java Целия файл

@@ -12,4 +12,8 @@ public class MappingCol {
private Integer level;
private String descript;
private String type;
private String select;
private String search;
private String export;
private String require;
}

Зареждане…
Отказ
Запис