| @@ -1,2 +1,3 @@ | |||||
| # Default ignored files | # Default ignored files | ||||
| /workspace.xml | /workspace.xml | ||||
| /inspectionProfiles/Project_Default.xml | |||||
| @@ -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> | |||||
| @@ -22,14 +22,15 @@ | |||||
| setAuthenticated(user) { | setAuthenticated(user) { | ||||
| if (user) { | if (user) { | ||||
| localStorage.setItem('username', user.username); | 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 { | } else { | ||||
| this.logout(); | this.logout(); | ||||
| } | } | ||||
| this.$router.replace({ name: 'asset_group' }); | |||||
| }, | }, | ||||
| logout() { | logout() { | ||||
| this.$axios.get('/logout').then((resp) => { | |||||
| this.$axios.get('/account/logout').then((resp) => { | |||||
| console.log(resp); | console.log(resp); | ||||
| }) | }) | ||||
| .catch(function (resp) { | .catch(function (resp) { | ||||
| @@ -1,201 +1,397 @@ | |||||
| <template> | <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 | <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> | </v-btn> | ||||
| </template> | </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> | </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> | </div> | ||||
| </template> | </template> | ||||
| <script> | <script> | ||||
| import axios from 'axios'; | |||||
| export default { | export default { | ||||
| name: 'AssetGroup', | |||||
| data () { | |||||
| name: '', | |||||
| data() { | |||||
| return { | return { | ||||
| search: '', | |||||
| select: null, | |||||
| reportconfs: [], | |||||
| date: new Date().toISOString().substr(0, 10), | |||||
| menu2: false, | |||||
| dialogInsert: false, | |||||
| dialogModify: false, | |||||
| dialogNewAssertGroup: false, | |||||
| // dialogSearch: false, | |||||
| title: '資訊資產群組', | |||||
| headers: [ | 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: { | 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> | </script> | ||||
| @@ -46,9 +46,9 @@ | |||||
| :to="item.route" | :to="item.route" | ||||
| class="px-0 pl-5" | 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-content> | ||||
| <v-list-item-title class="font-weight-bold subtitle-2"> | <v-list-item-title class="font-weight-bold subtitle-2"> | ||||
| {{ item.text }} | {{ item.text }} | ||||
| @@ -65,33 +65,80 @@ | |||||
| dark | dark | ||||
| dense | dense | ||||
| > | > | ||||
| <v-app-bar-nav-icon @click.stop="drawer = !drawer" /> | |||||
| <v-app-bar-nav-icon @click.stop="drawer = !drawer"/> | |||||
| <v-toolbar-title | <v-toolbar-title | ||||
| style="width: 400px" | style="width: 400px" | ||||
| class="ml-0 pl-4" | class="ml-0 pl-4" | ||||
| > | > | ||||
| <span class="hidden-sm-and-down">資訊資產管理系統</span> | <span class="hidden-sm-and-down">資訊資產管理系統</span> | ||||
| </v-toolbar-title> | </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-app-bar> | ||||
| <v-content> | <v-content> | ||||
| <keep-alive> | |||||
| <router-view></router-view> | |||||
| </keep-alive> | |||||
| <keep-alive> | |||||
| <router-view></router-view> | |||||
| </keep-alive> | |||||
| </v-content> | </v-content> | ||||
| <v-snackbar v-model="error" top :timeout="2500"> | <v-snackbar v-model="error" top :timeout="2500"> | ||||
| {{ message }} | {{ message }} | ||||
| @@ -108,19 +155,51 @@ | |||||
| <script> | <script> | ||||
| export default { | export default { | ||||
| components: { | |||||
| }, | |||||
| components: {}, | |||||
| props: { | props: { | ||||
| source: String, | 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.$root.$on('showError', (message) => { | ||||
| this.error = true; | this.error = true; | ||||
| this.message = message; | this.message = message; | ||||
| @@ -128,15 +207,15 @@ | |||||
| }, | }, | ||||
| computed: { | computed: { | ||||
| isAdmin() { | isAdmin() { | ||||
| let roles = localStorage.getItem('roles'); | |||||
| return (roles != null && roles.indexOf('ADMIN') >= 0 ); | |||||
| let level = localStorage.getItem('level'); | |||||
| return (level != null && level === '0'); | |||||
| }, | }, | ||||
| }, | }, | ||||
| mounted() { | mounted() { | ||||
| this.getRoutes(); | this.getRoutes(); | ||||
| }, | }, | ||||
| methods: { | methods: { | ||||
| logout(){ | |||||
| logout() { | |||||
| this.$emit("authenticated", null); | this.$emit("authenticated", null); | ||||
| }, | }, | ||||
| async getRoutes() { | async getRoutes() { | ||||
| @@ -9,10 +9,96 @@ | |||||
| inset | inset | ||||
| vertical | 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-dialog | ||||
| v-model="dialogInsert" | v-model="dialogInsert" | ||||
| max-width="500px" | |||||
| @click:outside="close" | @click:outside="close" | ||||
| > | > | ||||
| <template v-slot:activator="{ on, attrs }"> | <template v-slot:activator="{ on, attrs }"> | ||||
| @@ -31,64 +117,45 @@ | |||||
| <v-card-title> | <v-card-title> | ||||
| <span class="headline font-weight-bold">新增</span> | <span class="headline font-weight-bold">新增</span> | ||||
| </v-card-title> | </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-card-actions> | ||||
| <v-spacer></v-spacer> | <v-spacer></v-spacer> | ||||
| <v-btn | <v-btn | ||||
| @@ -120,7 +187,7 @@ | |||||
| v-bind="attrs" | v-bind="attrs" | ||||
| v-on="on" | v-on="on" | ||||
| icon | icon | ||||
| @click="modifyItem = item;" | |||||
| @click="modifyItem = JSON.parse(JSON.stringify(item))" | |||||
| > | > | ||||
| <v-icon>mdi-pencil</v-icon> | <v-icon>mdi-pencil</v-icon> | ||||
| </v-btn> | </v-btn> | ||||
| @@ -129,28 +196,42 @@ | |||||
| <v-card-title> | <v-card-title> | ||||
| <span class="headline font-weight-bold">修改</span> | <span class="headline font-weight-bold">修改</span> | ||||
| </v-card-title> | </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-card-actions> | ||||
| <v-spacer></v-spacer> | <v-spacer></v-spacer> | ||||
| <v-btn | <v-btn | ||||
| @@ -187,94 +268,144 @@ | |||||
| return { | return { | ||||
| dialogInsert: false, | dialogInsert: false, | ||||
| dialogModify: false, | dialogModify: false, | ||||
| dialogSearch: false, | |||||
| title: '', | title: '', | ||||
| headers: [ | |||||
| ], | |||||
| headers: [], | |||||
| cols: {}, | |||||
| items: [], | items: [], | ||||
| modifyItem: {} | |||||
| select: [], | |||||
| required: [], | |||||
| insertItem: {}, | |||||
| modifyItem: {}, | |||||
| selectItem: {}, | |||||
| searchItem: {}, | |||||
| mockSearch: false, | |||||
| } | } | ||||
| }, | }, | ||||
| mounted() { | |||||
| async mounted() { | |||||
| this.getHeaders(); | this.getHeaders(); | ||||
| this.getInventories(); | this.getInventories(); | ||||
| console.log(this.$route.params.tablename); | |||||
| this.getTitle(); | |||||
| this.getSelectItem(); | |||||
| }, | }, | ||||
| computed: { | computed: { | ||||
| tablename() { | |||||
| return this.$route.params.tablename; | |||||
| } | |||||
| }, | |||||
| watch: { | |||||
| tablename() { | 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: { | methods: { | ||||
| log() { | log() { | ||||
| alert('as'); | 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.$axios.get(`/headers?tablename=${this.tablename}`).then((resp) => { | ||||
| this.cols = resp.data.data; | |||||
| resp.data.data.forEach((item) => { | 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) => { | this.$axios.get(`/inventory?tablename=${this.tablename}`).then((resp) => { | ||||
| console.log(resp); | |||||
| this.items = resp.data.data; | 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.dialogInsert = false; | ||||
| this.dialogModify = 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; | item.tablename = this.tablename; | ||||
| console.log(item); | |||||
| this.$axios.put(`/inventory?`, item).then(() => { | this.$axios.put(`/inventory?`, item).then(() => { | ||||
| this.getInventories(); | |||||
| this.close(); | |||||
| this.getInventories(); | |||||
| this.close(); | |||||
| } | } | ||||
| ); | ); | ||||
| }, | }, | ||||
| async deleteOne(item) { | |||||
| deleteOne(item) { | |||||
| let yes = confirm('確定刪除'); | let yes = confirm('確定刪除'); | ||||
| if (yes) { | if (yes) { | ||||
| alert('已刪除'); | |||||
| this.$axios.delete(`/deleteOne?tablename=${this.tablename}&&id=${item.id}`).then(() => { | |||||
| this.getInventories(); | |||||
| alert('已刪除'); | |||||
| }); | |||||
| } | } | ||||
| console.log(item); | console.log(item); | ||||
| }, | }, | ||||
| exportFile() { | |||||
| let yes = confirm('確定匯出'); | |||||
| if (yes) { | |||||
| // this.$axios.delete(`/deleteOne?tablename=${this.tablename}&&id=${item.id}`).then(() => { | |||||
| // this.getInventories(); | |||||
| // }); | |||||
| } | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| </script> | </script> | ||||
| @@ -1,19 +1,26 @@ | |||||
| <template> | <template> | ||||
| <v-main> | <v-main> | ||||
| <v-container | <v-container | ||||
| class='fill-height' | |||||
| class='fill-height primary lighten-3 d-flex' | |||||
| fluid | fluid | ||||
| > | > | ||||
| <v-row | <v-row | ||||
| align='center' | align='center' | ||||
| justify='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 | <v-col | ||||
| cols='12' | cols='12' | ||||
| sm='8' | sm='8' | ||||
| md='4' | md='4' | ||||
| > | > | ||||
| <v-card class='elevation-12'> | |||||
| <v-card class='elevation-12 grey lighten-3'> | |||||
| <v-toolbar | <v-toolbar | ||||
| color='primary' | color='primary' | ||||
| dark | dark | ||||
| @@ -25,7 +32,7 @@ | |||||
| <v-card-text> | <v-card-text> | ||||
| <v-form> | <v-form> | ||||
| <v-text-field | <v-text-field | ||||
| v-model='input.username' | |||||
| v-model='input.account' | |||||
| label='Login' | label='Login' | ||||
| name='login' | name='login' | ||||
| prepend-icon='mdi-account' | prepend-icon='mdi-account' | ||||
| @@ -44,7 +51,7 @@ | |||||
| </v-card-text> | </v-card-text> | ||||
| <v-card-actions> | <v-card-actions> | ||||
| <v-spacer /> | <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-actions> | ||||
| </v-card> | </v-card> | ||||
| </v-col> | </v-col> | ||||
| @@ -68,7 +75,7 @@ | |||||
| data() { | data() { | ||||
| return { | return { | ||||
| input: { | input: { | ||||
| username: '', | |||||
| account: '', | |||||
| password: '', | password: '', | ||||
| }, | }, | ||||
| loginError : false, | loginError : false, | ||||
| @@ -81,28 +88,25 @@ | |||||
| this.$emit('authenticated', | this.$emit('authenticated', | ||||
| { | { | ||||
| 'username':'aaa', | 'username':'aaa', | ||||
| 'roles': 'aaa', | |||||
| 'department': 'aaa', | |||||
| 'level': '1' | |||||
| }); | }); | ||||
| }, | }, | ||||
| login() { | login() { | ||||
| this.loginError = false; | this.loginError = false; | ||||
| const _this = this; | const _this = this; | ||||
| if(this.input.username !== '' && this.input.password !== '') { | 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) { | if (resp.status === 200) { | ||||
| //成功 | |||||
| const json = resp.data; | const json = resp.data; | ||||
| if (json.status === 'OK') { | |||||
| if (json.code === 200) { | |||||
| _this.$emit('authenticated', | _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 { | } else { | ||||
| _this.message = json.message; | _this.message = json.message; | ||||
| _this.loginError = true; | _this.loginError = true; | ||||
| @@ -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> | |||||
| @@ -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> | |||||
| @@ -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> | |||||
| @@ -4,6 +4,8 @@ import Login from '@/components/Login' | |||||
| import Home from '../components/Home'; | import Home from '../components/Home'; | ||||
| import AssetGroup from '../components/AssetGroup'; | import AssetGroup from '../components/AssetGroup'; | ||||
| import Inventory from '../components/Inventory'; | import Inventory from '../components/Inventory'; | ||||
| // import Search from '../components/Search'; | |||||
| import MockSearch from '../components/MockSearch'; | |||||
| Vue.use(Router); | Vue.use(Router); | ||||
| @@ -14,20 +16,25 @@ export const constantRoutes = [ | |||||
| component: Login, | component: Login, | ||||
| }, | }, | ||||
| { | { | ||||
| path: '/home', | |||||
| path: '/', | |||||
| component: Home, | component: Home, | ||||
| name: 'home', | name: 'home', | ||||
| children: [ | children: [ | ||||
| { | { | ||||
| path: '/asset_group', | |||||
| path: 'asset_group', | |||||
| name: 'asset_group', | name: 'asset_group', | ||||
| component: AssetGroup | component: AssetGroup | ||||
| }, | }, | ||||
| { | { | ||||
| path: '/inventory/:tablename', | |||||
| path: 'inventory/:tablename', | |||||
| name: 'inventory', | name: 'inventory', | ||||
| component: Inventory | component: Inventory | ||||
| }, | }, | ||||
| { | |||||
| path: 'search', | |||||
| name: 'search', | |||||
| component: MockSearch | |||||
| }, | |||||
| ] | ] | ||||
| } | } | ||||
| ]; | ]; | ||||
| @@ -1,8 +1,6 @@ | |||||
| package com.moze.rms.config; | 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.Jdbi; | ||||
| import org.jdbi.v3.core.statement.SqlLogger; | import org.jdbi.v3.core.statement.SqlLogger; | ||||
| import org.jdbi.v3.core.statement.StatementContext; | import org.jdbi.v3.core.statement.StatementContext; | ||||
| @@ -66,4 +64,16 @@ public class JdbiFactory { | |||||
| public InventoryDAO inventoryDAO(Jdbi jdbi) { | public InventoryDAO inventoryDAO(Jdbi jdbi) { | ||||
| return jdbi.onDemand(InventoryDAO.class); | 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); | |||||
| } | |||||
| } | } | ||||
| @@ -1,10 +1,31 @@ | |||||
| package com.moze.rms.controller; | 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 | @RestController | ||||
| @RequestMapping("/api/account") | @RequestMapping("/api/account") | ||||
| public class AccountController { | 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); | |||||
| } | |||||
| } | } | ||||
| @@ -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))); | |||||
| } | |||||
| } | |||||
| @@ -4,10 +4,13 @@ package com.moze.rms.controller; | |||||
| import com.moze.rms.dao.InventoryDAO; | import com.moze.rms.dao.InventoryDAO; | ||||
| import com.moze.rms.dao.MappingColDAO; | import com.moze.rms.dao.MappingColDAO; | ||||
| import com.moze.rms.dao.MappingTableDAO; | import com.moze.rms.dao.MappingTableDAO; | ||||
| import com.moze.rms.entity.dto.SelectItemDTO; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.web.bind.annotation.*; | import org.springframework.web.bind.annotation.*; | ||||
| import java.util.Map; | |||||
| import java.util.*; | |||||
| import java.util.function.Function; | |||||
| import java.util.stream.Collectors; | |||||
| @RestController | @RestController | ||||
| @RequestMapping("/api") | @RequestMapping("/api") | ||||
| @@ -38,7 +41,6 @@ public class InventoryController { | |||||
| @GetMapping("/headers") | @GetMapping("/headers") | ||||
| public JsonResult getHeaders(@RequestParam String tablename) { | public JsonResult getHeaders(@RequestParam String tablename) { | ||||
| return new JsonResult(StatusCode.SUCCESS, mappingColDAO.findByTable(tablename)); | return new JsonResult(StatusCode.SUCCESS, mappingColDAO.findByTable(tablename)); | ||||
| } | } | ||||
| @GetMapping("/inventory") | @GetMapping("/inventory") | ||||
| @@ -46,6 +48,13 @@ public class InventoryController { | |||||
| return new JsonResult(StatusCode.SUCCESS, inventoryDAO.getInventoryByTablename(tablename)); | 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") | @PutMapping("/inventory") | ||||
| public JsonResult modifyInventory(@RequestBody Map<String, Object> data) { | public JsonResult modifyInventory(@RequestBody Map<String, Object> data) { | ||||
| try { | 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); | |||||
| } | |||||
| } | } | ||||
| @@ -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(); | |||||
| } | |||||
| } | |||||
| @@ -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(); | |||||
| } | |||||
| @@ -1,12 +1,14 @@ | |||||
| package com.moze.rms.dao; | package com.moze.rms.dao; | ||||
| import com.moze.rms.entity.dto.SelectItemDTO; | |||||
| import org.jdbi.v3.core.Handle; | import org.jdbi.v3.core.Handle; | ||||
| import org.jdbi.v3.sqlobject.SqlObject; | import org.jdbi.v3.sqlobject.SqlObject; | ||||
| import org.jdbi.v3.sqlobject.config.RegisterBeanMapper; | import org.jdbi.v3.sqlobject.config.RegisterBeanMapper; | ||||
| import org.jdbi.v3.sqlobject.statement.SqlQuery; | import org.jdbi.v3.sqlobject.statement.SqlQuery; | ||||
| import org.jdbi.v3.sqlobject.statement.SqlUpdate; | import org.jdbi.v3.sqlobject.statement.SqlUpdate; | ||||
| import java.util.Iterator; | |||||
| import java.util.List; | import java.util.List; | ||||
| import java.util.Map; | import java.util.Map; | ||||
| @@ -26,10 +28,48 @@ public interface InventoryDAO extends SqlObject { | |||||
| String sql = "update " + data.get("tablename") + " set "; | String sql = "update " + data.get("tablename") + " set "; | ||||
| for (Map.Entry<String, Object> entry : data.entrySet()) { | for (Map.Entry<String, Object> entry : data.entrySet()) { | ||||
| if (!entry.getKey().equals("id") && !entry.getKey().equals("tablename")) | 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(); | 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); | |||||
| } | |||||
| } | } | ||||
| @@ -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; | |||||
| } | |||||
| @@ -12,4 +12,8 @@ public class MappingCol { | |||||
| private Integer level; | private Integer level; | ||||
| private String descript; | private String descript; | ||||
| private String type; | private String type; | ||||
| private String select; | |||||
| private String search; | |||||
| private String export; | |||||
| private String require; | |||||
| } | } | ||||