diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/404.html b/404.html new file mode 100644 index 0000000..ce3cde6 --- /dev/null +++ b/404.html @@ -0,0 +1,21 @@ + + + + + + kite-notes + + + + + + + + + +

404

Looks like we've got some broken links.
+ Take me home. +
+ + + diff --git a/assets/css/0.styles.f5731900.css b/assets/css/0.styles.f5731900.css new file mode 100644 index 0000000..02b51a4 --- /dev/null +++ b/assets/css/0.styles.f5731900.css @@ -0,0 +1 @@ +code[class*=language-],pre[class*=language-]{color:#ccc;background:none;font-family:Consolas,Monaco,Andale Mono,Ubuntu Mono,monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;hyphens:none}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#2d2d2d}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.block-comment,.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#999}.token.punctuation{color:#ccc}.token.attr-name,.token.deleted,.token.namespace,.token.tag{color:#e2777a}.token.function-name{color:#6196cc}.token.boolean,.token.function,.token.number{color:#f08d49}.token.class-name,.token.constant,.token.property,.token.symbol{color:#f8c555}.token.atrule,.token.builtin,.token.important,.token.keyword,.token.selector{color:#cc99cd}.token.attr-value,.token.char,.token.regex,.token.string,.token.variable{color:#7ec699}.token.entity,.token.operator,.token.url{color:#67cdcc}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}.token.inserted{color:green}.theme-default-content code{color:#476582;padding:.25rem .5rem;margin:0;font-size:.85em;background-color:rgba(27,31,35,.05);border-radius:3px}.theme-default-content code .token.deleted{color:#ec5975}.theme-default-content code .token.inserted{color:#3eaf7c}.theme-default-content pre,.theme-default-content pre[class*=language-]{line-height:1.4;padding:1.25rem 1.5rem;margin:.85rem 0;background-color:#282c34;border-radius:6px;overflow:auto}.theme-default-content pre[class*=language-] code,.theme-default-content pre code{color:#fff;padding:0;background-color:transparent;border-radius:0}div[class*=language-]{position:relative;background-color:#282c34;border-radius:6px}div[class*=language-] .highlight-lines{-webkit-user-select:none;user-select:none;padding-top:1.3rem;position:absolute;top:0;left:0;width:100%;line-height:1.4}div[class*=language-] .highlight-lines .highlighted{background-color:rgba(0,0,0,.66)}div[class*=language-] pre,div[class*=language-] pre[class*=language-]{background:transparent;position:relative;z-index:1}div[class*=language-]:before{position:absolute;z-index:3;top:.8em;right:1em;font-size:.75rem;color:hsla(0,0%,100%,.4)}div[class*=language-]:not(.line-numbers-mode) .line-numbers-wrapper{display:none}div[class*=language-].line-numbers-mode .highlight-lines .highlighted{position:relative}div[class*=language-].line-numbers-mode .highlight-lines .highlighted:before{content:" ";position:absolute;z-index:3;left:0;top:0;display:block;width:3.5rem;height:100%;background-color:rgba(0,0,0,.66)}div[class*=language-].line-numbers-mode pre{padding-left:4.5rem;vertical-align:middle}div[class*=language-].line-numbers-mode .line-numbers-wrapper{position:absolute;top:0;width:3.5rem;text-align:center;color:hsla(0,0%,100%,.3);padding:1.25rem 0;line-height:1.4}div[class*=language-].line-numbers-mode .line-numbers-wrapper br{-webkit-user-select:none;user-select:none}div[class*=language-].line-numbers-mode .line-numbers-wrapper .line-number{position:relative;z-index:4;-webkit-user-select:none;user-select:none;font-size:.85em}div[class*=language-].line-numbers-mode:after{content:"";position:absolute;z-index:2;top:0;left:0;width:3.5rem;height:100%;border-radius:6px 0 0 6px;border-right:1px solid rgba(0,0,0,.66);background-color:#282c34}div[class~=language-js]:before{content:"js"}div[class~=language-ts]:before{content:"ts"}div[class~=language-html]:before{content:"html"}div[class~=language-md]:before{content:"md"}div[class~=language-vue]:before{content:"vue"}div[class~=language-css]:before{content:"css"}div[class~=language-sass]:before{content:"sass"}div[class~=language-scss]:before{content:"scss"}div[class~=language-less]:before{content:"less"}div[class~=language-stylus]:before{content:"stylus"}div[class~=language-go]:before{content:"go"}div[class~=language-java]:before{content:"java"}div[class~=language-c]:before{content:"c"}div[class~=language-sh]:before{content:"sh"}div[class~=language-yaml]:before{content:"yaml"}div[class~=language-py]:before{content:"py"}div[class~=language-docker]:before{content:"docker"}div[class~=language-dockerfile]:before{content:"dockerfile"}div[class~=language-makefile]:before{content:"makefile"}div[class~=language-javascript]:before{content:"js"}div[class~=language-typescript]:before{content:"ts"}div[class~=language-markup]:before{content:"html"}div[class~=language-markdown]:before{content:"md"}div[class~=language-json]:before{content:"json"}div[class~=language-ruby]:before{content:"rb"}div[class~=language-python]:before{content:"py"}div[class~=language-bash]:before{content:"sh"}div[class~=language-php]:before{content:"php"}.custom-block .custom-block-title{font-weight:600;margin-bottom:-.4rem}.custom-block.danger,.custom-block.tip,.custom-block.warning{padding:.1rem 1.5rem;border-left-width:.5rem;border-left-style:solid;margin:1rem 0}.custom-block.tip{background-color:#f3f5f7;border-color:#42b983}.custom-block.warning{background-color:rgba(255,229,100,.3);border-color:#e7c000;color:#6b5900}.custom-block.warning .custom-block-title{color:#b29400}.custom-block.warning a{color:#2c3e50}.custom-block.danger{background-color:#ffe6e6;border-color:#c00;color:#4d0000}.custom-block.danger .custom-block-title{color:#900}.custom-block.danger a{color:#2c3e50}.custom-block.details{display:block;position:relative;border-radius:2px;margin:1.6em 0;padding:1.6em;background-color:#eee}.custom-block.details h4{margin-top:0}.custom-block.details figure:last-child,.custom-block.details p:last-child{margin-bottom:0;padding-bottom:0}.custom-block.details summary{outline:none;cursor:pointer}.arrow{display:inline-block;width:0;height:0}.arrow.up{border-bottom:6px solid #ccc}.arrow.down,.arrow.up{border-left:4px solid transparent;border-right:4px solid transparent}.arrow.down{border-top:6px solid #ccc}.arrow.right{border-left:6px solid #ccc}.arrow.left,.arrow.right{border-top:4px solid transparent;border-bottom:4px solid transparent}.arrow.left{border-right:6px solid #ccc}.theme-default-content:not(.custom){max-width:740px;margin:0 auto;padding:2rem 2.5rem}@media (max-width:959px){.theme-default-content:not(.custom){padding:2rem}}@media (max-width:419px){.theme-default-content:not(.custom){padding:1.5rem}}.table-of-contents .badge{vertical-align:middle}body,html{padding:0;margin:0;background-color:#fff}body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-size:16px;color:#2c3e50}.page{padding-left:20rem}.navbar{z-index:20;right:0;height:3.6rem;background-color:#fff;box-sizing:border-box;border-bottom:1px solid #eaecef}.navbar,.sidebar-mask{position:fixed;top:0;left:0}.sidebar-mask{z-index:9;width:100vw;height:100vh;display:none}.sidebar{font-size:16px;background-color:#fff;width:20rem;position:fixed;z-index:10;margin:0;top:3.6rem;left:0;bottom:0;box-sizing:border-box;border-right:1px solid #eaecef;overflow-y:auto}.theme-default-content:not(.custom)>:first-child{margin-top:3.6rem}.theme-default-content:not(.custom) a:hover{text-decoration:underline}.theme-default-content:not(.custom) p.demo{padding:1rem 1.5rem;border:1px solid #ddd;border-radius:4px}.theme-default-content:not(.custom) img{max-width:100%}.theme-default-content.custom{padding:0;margin:0}.theme-default-content.custom img{max-width:100%}a{font-weight:500;text-decoration:none}a,p a code{color:#3eaf7c}p a code{font-weight:400}kbd{background:#eee;border:.15rem solid #ddd;border-bottom:.25rem solid #ddd;border-radius:.15rem;padding:0 .15em}blockquote{font-size:1rem;color:#999;border-left:.2rem solid #dfe2e5;margin:1rem 0;padding:.25rem 0 .25rem 1rem}blockquote>p{margin:0}ol,ul{padding-left:1.2em}strong{font-weight:600}h1,h2,h3,h4,h5,h6{font-weight:600;line-height:1.25}.theme-default-content:not(.custom)>h1,.theme-default-content:not(.custom)>h2,.theme-default-content:not(.custom)>h3,.theme-default-content:not(.custom)>h4,.theme-default-content:not(.custom)>h5,.theme-default-content:not(.custom)>h6{margin-top:-3.1rem;padding-top:4.6rem;margin-bottom:0}.theme-default-content:not(.custom)>h1:first-child,.theme-default-content:not(.custom)>h2:first-child,.theme-default-content:not(.custom)>h3:first-child,.theme-default-content:not(.custom)>h4:first-child,.theme-default-content:not(.custom)>h5:first-child,.theme-default-content:not(.custom)>h6:first-child{margin-top:-1.5rem;margin-bottom:1rem}.theme-default-content:not(.custom)>h1:first-child+.custom-block,.theme-default-content:not(.custom)>h1:first-child+p,.theme-default-content:not(.custom)>h1:first-child+pre,.theme-default-content:not(.custom)>h2:first-child+.custom-block,.theme-default-content:not(.custom)>h2:first-child+p,.theme-default-content:not(.custom)>h2:first-child+pre,.theme-default-content:not(.custom)>h3:first-child+.custom-block,.theme-default-content:not(.custom)>h3:first-child+p,.theme-default-content:not(.custom)>h3:first-child+pre,.theme-default-content:not(.custom)>h4:first-child+.custom-block,.theme-default-content:not(.custom)>h4:first-child+p,.theme-default-content:not(.custom)>h4:first-child+pre,.theme-default-content:not(.custom)>h5:first-child+.custom-block,.theme-default-content:not(.custom)>h5:first-child+p,.theme-default-content:not(.custom)>h5:first-child+pre,.theme-default-content:not(.custom)>h6:first-child+.custom-block,.theme-default-content:not(.custom)>h6:first-child+p,.theme-default-content:not(.custom)>h6:first-child+pre{margin-top:2rem}h1:focus .header-anchor,h1:hover .header-anchor,h2:focus .header-anchor,h2:hover .header-anchor,h3:focus .header-anchor,h3:hover .header-anchor,h4:focus .header-anchor,h4:hover .header-anchor,h5:focus .header-anchor,h5:hover .header-anchor,h6:focus .header-anchor,h6:hover .header-anchor{opacity:1}h1{font-size:2.2rem}h2{font-size:1.65rem;padding-bottom:.3rem;border-bottom:1px solid #eaecef}h3{font-size:1.35rem}a.header-anchor{font-size:.85em;float:left;margin-left:-.87em;padding-right:.23em;margin-top:.125em;opacity:0}a.header-anchor:focus,a.header-anchor:hover{text-decoration:none}.line-number,code,kbd{font-family:source-code-pro,Menlo,Monaco,Consolas,Courier New,monospace}ol,p,ul{line-height:1.7}hr{border:0;border-top:1px solid #eaecef}table{border-collapse:collapse;margin:1rem 0;display:block;overflow-x:auto}tr{border-top:1px solid #dfe2e5}tr:nth-child(2n){background-color:#f6f8fa}td,th{border:1px solid #dfe2e5;padding:.6em 1em}.theme-container.sidebar-open .sidebar-mask{display:block}.theme-container.no-navbar .theme-default-content:not(.custom)>h1,.theme-container.no-navbar h2,.theme-container.no-navbar h3,.theme-container.no-navbar h4,.theme-container.no-navbar h5,.theme-container.no-navbar h6{margin-top:1.5rem;padding-top:0}.theme-container.no-navbar .sidebar{top:0}@media (min-width:720px){.theme-container.no-sidebar .sidebar{display:none}.theme-container.no-sidebar .page{padding-left:0}}@media (max-width:959px){.sidebar{font-size:15px;width:16.4rem}.page{padding-left:16.4rem}}@media (max-width:719px){.sidebar{top:0;padding-top:3.6rem;transform:translateX(-100%);transition:transform .2s ease}.page{padding-left:0}.theme-container.sidebar-open .sidebar{transform:translateX(0)}.theme-container.no-navbar .sidebar{padding-top:0}}@media (max-width:419px){h1{font-size:1.9rem}.theme-default-content div[class*=language-]{margin:.85rem -1.5rem;border-radius:0}}#nprogress{pointer-events:none}#nprogress .bar{background:#3eaf7c;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #3eaf7c,0 0 5px #3eaf7c;opacity:1;transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border-color:#3eaf7c transparent transparent #3eaf7c;border-style:solid;border-width:2px;border-radius:50%;-webkit-animation:nprogress-spinner .4s linear infinite;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@-webkit-keyframes nprogress-spinner{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}@keyframes nprogress-spinner{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.icon.outbound{color:#aaa;display:inline-block;vertical-align:middle;position:relative;top:-1px}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.home{padding:3.6rem 2rem 0;max-width:960px;margin:0 auto;display:block}.home .hero{text-align:center}.home .hero img{max-width:100%;max-height:280px;display:block;margin:3rem auto 1.5rem}.home .hero h1{font-size:3rem}.home .hero .action,.home .hero .description,.home .hero h1{margin:1.8rem auto}.home .hero .description{max-width:35rem;font-size:1.6rem;line-height:1.3;color:#6a8bad}.home .hero .action-button{display:inline-block;font-size:1.2rem;color:#fff;background-color:#3eaf7c;padding:.8rem 1.6rem;border-radius:4px;transition:background-color .1s ease;box-sizing:border-box;border-bottom:1px solid #389d70}.home .hero .action-button:hover{background-color:#4abf8a}.home .features{border-top:1px solid #eaecef;padding:1.2rem 0;margin-top:2.5rem;display:flex;flex-wrap:wrap;align-items:flex-start;align-content:stretch;justify-content:space-between}.home .feature{flex-grow:1;flex-basis:30%;max-width:30%}.home .feature h2{font-size:1.4rem;font-weight:500;border-bottom:none;padding-bottom:0;color:#3a5169}.home .feature p{color:#4e6e8e}.home .footer{padding:2.5rem;border-top:1px solid #eaecef;text-align:center;color:#4e6e8e}@media (max-width:719px){.home .features{flex-direction:column}.home .feature{max-width:100%;padding:0 2.5rem}}@media (max-width:419px){.home{padding-left:1.5rem;padding-right:1.5rem}.home .hero img{max-height:210px;margin:2rem auto 1.2rem}.home .hero h1{font-size:2rem}.home .hero .action,.home .hero .description,.home .hero h1{margin:1.2rem auto}.home .hero .description{font-size:1.2rem}.home .hero .action-button{font-size:1rem;padding:.6rem 1.2rem}.home .feature h2{font-size:1.25rem}}.search-box{display:inline-block;position:relative;margin-right:1rem}.search-box input{cursor:text;width:10rem;height:2rem;color:#4e6e8e;display:inline-block;border:1px solid #cfd4db;border-radius:2rem;font-size:.9rem;line-height:2rem;padding:0 .5rem 0 2rem;outline:none;transition:all .2s ease;background:#fff url(/kite-notes/assets/img/search.83621669.svg) .6rem .5rem no-repeat;background-size:1rem}.search-box input:focus{cursor:auto;border-color:#3eaf7c}.search-box .suggestions{background:#fff;width:20rem;position:absolute;top:2rem;border:1px solid #cfd4db;border-radius:6px;padding:.4rem;list-style-type:none}.search-box .suggestions.align-right{right:0}.search-box .suggestion{line-height:1.4;padding:.4rem .6rem;border-radius:4px;cursor:pointer}.search-box .suggestion a{white-space:normal;color:#5d82a6}.search-box .suggestion a .page-title{font-weight:600}.search-box .suggestion a .header{font-size:.9em;margin-left:.25em}.search-box .suggestion.focused{background-color:#f3f4f5}.search-box .suggestion.focused a{color:#3eaf7c}@media (max-width:959px){.search-box input{cursor:pointer;width:0;border-color:transparent;position:relative}.search-box input:focus{cursor:text;left:0;width:10rem}}@media (-ms-high-contrast:none){.search-box input{height:2rem}}@media (max-width:959px) and (min-width:719px){.search-box .suggestions{left:0}}@media (max-width:719px){.search-box{margin-right:0}.search-box input{left:1rem}.search-box .suggestions{right:0}}@media (max-width:419px){.search-box .suggestions{width:calc(100vw - 4rem)}.search-box input:focus{width:8rem}}.sidebar-button{cursor:pointer;display:none;width:1.25rem;height:1.25rem;position:absolute;padding:.6rem;top:.6rem;left:1rem}.sidebar-button .icon{display:block;width:1.25rem;height:1.25rem}@media (max-width:719px){.sidebar-button{display:block}}.dropdown-enter,.dropdown-leave-to{height:0!important}.dropdown-wrapper{cursor:pointer}.dropdown-wrapper .dropdown-title,.dropdown-wrapper .mobile-dropdown-title{display:block;font-size:.9rem;font-family:inherit;cursor:inherit;padding:inherit;line-height:1.4rem;background:transparent;border:none;font-weight:500;color:#2c3e50}.dropdown-wrapper .dropdown-title:hover,.dropdown-wrapper .mobile-dropdown-title:hover{border-color:transparent}.dropdown-wrapper .dropdown-title .arrow,.dropdown-wrapper .mobile-dropdown-title .arrow{vertical-align:middle;margin-top:-1px;margin-left:.4rem}.dropdown-wrapper .mobile-dropdown-title{display:none;font-weight:600}.dropdown-wrapper .mobile-dropdown-title font-size inherit:hover{color:#3eaf7c}.dropdown-wrapper .nav-dropdown .dropdown-item{color:inherit;line-height:1.7rem}.dropdown-wrapper .nav-dropdown .dropdown-item h4{margin:.45rem 0 0;border-top:1px solid #eee;padding:1rem 1.5rem .45rem 1.25rem}.dropdown-wrapper .nav-dropdown .dropdown-item .dropdown-subitem-wrapper{padding:0;list-style:none}.dropdown-wrapper .nav-dropdown .dropdown-item .dropdown-subitem-wrapper .dropdown-subitem{font-size:.9em}.dropdown-wrapper .nav-dropdown .dropdown-item a{display:block;line-height:1.7rem;position:relative;border-bottom:none;font-weight:400;margin-bottom:0;padding:0 1.5rem 0 1.25rem}.dropdown-wrapper .nav-dropdown .dropdown-item a.router-link-active,.dropdown-wrapper .nav-dropdown .dropdown-item a:hover{color:#3eaf7c}.dropdown-wrapper .nav-dropdown .dropdown-item a.router-link-active:after{content:"";width:0;height:0;border-left:5px solid #3eaf7c;border-top:3px solid transparent;border-bottom:3px solid transparent;position:absolute;top:calc(50% - 2px);left:9px}.dropdown-wrapper .nav-dropdown .dropdown-item:first-child h4{margin-top:0;padding-top:0;border-top:0}@media (max-width:719px){.dropdown-wrapper.open .dropdown-title{margin-bottom:.5rem}.dropdown-wrapper .dropdown-title{display:none}.dropdown-wrapper .mobile-dropdown-title{display:block}.dropdown-wrapper .nav-dropdown{transition:height .1s ease-out;overflow:hidden}.dropdown-wrapper .nav-dropdown .dropdown-item h4{border-top:0;margin-top:0;padding-top:0}.dropdown-wrapper .nav-dropdown .dropdown-item>a,.dropdown-wrapper .nav-dropdown .dropdown-item h4{font-size:15px;line-height:2rem}.dropdown-wrapper .nav-dropdown .dropdown-item .dropdown-subitem{font-size:14px;padding-left:1rem}}@media (min-width:719px){.dropdown-wrapper{height:1.8rem}.dropdown-wrapper.open .nav-dropdown,.dropdown-wrapper:hover .nav-dropdown{display:block!important}.dropdown-wrapper.open:blur{display:none}.dropdown-wrapper .nav-dropdown{display:none;height:auto!important;box-sizing:border-box;max-height:calc(100vh - 2.7rem);overflow-y:auto;position:absolute;top:100%;right:0;background-color:#fff;padding:.6rem 0;border:1px solid;border-color:#ddd #ddd #ccc;text-align:left;border-radius:.25rem;white-space:nowrap;margin:0}}.nav-links{display:inline-block}.nav-links a{line-height:1.4rem;color:inherit}.nav-links a.router-link-active,.nav-links a:hover{color:#3eaf7c}.nav-links .nav-item{position:relative;display:inline-block;margin-left:1.5rem;line-height:2rem}.nav-links .nav-item:first-child{margin-left:0}.nav-links .repo-link{margin-left:1.5rem}@media (max-width:719px){.nav-links .nav-item,.nav-links .repo-link{margin-left:0}}@media (min-width:719px){.nav-links a.router-link-active,.nav-links a:hover{color:#2c3e50}.nav-item>a:not(.external).router-link-active,.nav-item>a:not(.external):hover{margin-bottom:-2px;border-bottom:2px solid #46bd87}}.navbar{padding:.7rem 1.5rem;line-height:2.2rem}.navbar a,.navbar img,.navbar span{display:inline-block}.navbar .logo{height:2.2rem;min-width:2.2rem;margin-right:.8rem;vertical-align:top}.navbar .site-name{font-size:1.3rem;font-weight:600;color:#2c3e50;position:relative}.navbar .links{padding-left:1.5rem;box-sizing:border-box;background-color:#fff;white-space:nowrap;font-size:.9rem;position:absolute;right:1.5rem;top:.7rem;display:flex}.navbar .links .search-box{flex:0 0 auto;vertical-align:top}@media (max-width:719px){.navbar{padding-left:4rem}.navbar .can-hide{display:none}.navbar .links{padding-left:1.5rem}.navbar .site-name{width:calc(100vw - 9.4rem);overflow:hidden;white-space:nowrap;text-overflow:ellipsis}}.page-edit{max-width:740px;margin:0 auto;padding:2rem 2.5rem}@media (max-width:959px){.page-edit{padding:2rem}}@media (max-width:419px){.page-edit{padding:1.5rem}}.page-edit{padding-top:1rem;padding-bottom:1rem;overflow:auto}.page-edit .edit-link{display:inline-block}.page-edit .edit-link a{color:#4e6e8e;margin-right:.25rem}.page-edit .last-updated{float:right;font-size:.9em}.page-edit .last-updated .prefix{font-weight:500;color:#4e6e8e}.page-edit .last-updated .time{font-weight:400;color:#767676}@media (max-width:719px){.page-edit .edit-link{margin-bottom:.5rem}.page-edit .last-updated{font-size:.8em;float:none;text-align:left}}.page-nav{max-width:740px;margin:0 auto;padding:2rem 2.5rem}@media (max-width:959px){.page-nav{padding:2rem}}@media (max-width:419px){.page-nav{padding:1.5rem}}.page-nav{padding-top:1rem;padding-bottom:0}.page-nav .inner{min-height:2rem;margin-top:0;border-top:1px solid #eaecef;padding-top:1rem;overflow:auto}.page-nav .next{float:right}.page{padding-bottom:2rem;display:block}.sidebar-group .sidebar-group{padding-left:.5em}.sidebar-group:not(.collapsable) .sidebar-heading:not(.clickable){cursor:auto;color:inherit}.sidebar-group.is-sub-group{padding-left:0}.sidebar-group.is-sub-group>.sidebar-heading{font-size:.95em;line-height:1.4;font-weight:400;padding-left:2rem}.sidebar-group.is-sub-group>.sidebar-heading:not(.clickable){opacity:.5}.sidebar-group.is-sub-group>.sidebar-group-items{padding-left:1rem}.sidebar-group.is-sub-group>.sidebar-group-items>li>.sidebar-link{font-size:.95em;border-left:none}.sidebar-group.depth-2>.sidebar-heading{border-left:none}.sidebar-heading{color:#2c3e50;transition:color .15s ease;cursor:pointer;font-size:1.1em;font-weight:700;padding:.35rem 1.5rem .35rem 1.25rem;width:100%;box-sizing:border-box;margin:0;border-left:.25rem solid transparent}.sidebar-heading.open,.sidebar-heading:hover{color:inherit}.sidebar-heading .arrow{position:relative;top:-.12em;left:.5em}.sidebar-heading.clickable.active{font-weight:600;color:#3eaf7c;border-left-color:#3eaf7c}.sidebar-heading.clickable:hover{color:#3eaf7c}.sidebar-group-items{transition:height .1s ease-out;font-size:.95em;overflow:hidden}.sidebar .sidebar-sub-headers{padding-left:1rem;font-size:.95em}a.sidebar-link{font-size:1em;font-weight:400;display:inline-block;color:#2c3e50;border-left:.25rem solid transparent;padding:.35rem 1rem .35rem 1.25rem;line-height:1.4;width:100%;box-sizing:border-box}a.sidebar-link:hover{color:#3eaf7c}a.sidebar-link.active{font-weight:600;color:#3eaf7c;border-left-color:#3eaf7c}.sidebar-group a.sidebar-link{padding-left:2rem}.sidebar-sub-headers a.sidebar-link{padding-top:.25rem;padding-bottom:.25rem;border-left:none}.sidebar-sub-headers a.sidebar-link.active{font-weight:500}.sidebar ul{padding:0;margin:0;list-style-type:none}.sidebar a{display:inline-block}.sidebar .nav-links{display:none;border-bottom:1px solid #eaecef;padding:.5rem 0 .75rem}.sidebar .nav-links a{font-weight:600}.sidebar .nav-links .nav-item,.sidebar .nav-links .repo-link{display:block;line-height:1.25rem;font-size:1.1em;padding:.5rem 0 .5rem 1.5rem}.sidebar>.sidebar-links{padding:1.5rem 0}.sidebar>.sidebar-links>li>a.sidebar-link{font-size:1.1em;line-height:1.7;font-weight:700}.sidebar>.sidebar-links>li:not(:first-child){margin-top:.75rem}@media (max-width:719px){.sidebar .nav-links{display:block}.sidebar .nav-links .dropdown-wrapper .nav-dropdown .dropdown-item a.router-link-active:after{top:calc(1rem - 2px)}.sidebar>.sidebar-links{padding:1rem 0}}.badge[data-v-cd6f89c2]{display:inline-block;font-size:14px;height:18px;line-height:18px;border-radius:3px;padding:0 6px;color:#fff}.badge.green[data-v-cd6f89c2],.badge.tip[data-v-cd6f89c2],.badge[data-v-cd6f89c2]{background-color:#42b983}.badge.error[data-v-cd6f89c2]{background-color:#da5961}.badge.warn[data-v-cd6f89c2],.badge.warning[data-v-cd6f89c2],.badge.yellow[data-v-cd6f89c2]{background-color:#e7c000}.badge+.badge[data-v-cd6f89c2]{margin-left:5px}.theme-code-block[data-v-492049b0]{display:none}.theme-code-block__active[data-v-492049b0]{display:block}.theme-code-block>pre[data-v-492049b0]{background-color:orange}.theme-code-group__nav[data-v-6667a46d]{margin-bottom:-35px;background-color:#282c34;padding-bottom:22px;border-top-left-radius:6px;border-top-right-radius:6px;padding-left:10px;padding-top:10px}.theme-code-group__ul[data-v-6667a46d]{margin:auto 0;padding-left:0;display:inline-flex;list-style:none}.theme-code-group__nav-tab[data-v-6667a46d]{border:0;padding:5px;cursor:pointer;background-color:transparent;font-size:.85em;line-height:1.4;color:hsla(0,0%,100%,.9);font-weight:600}.theme-code-group__nav-tab-active[data-v-6667a46d]{border-bottom:1px solid #42b983}.pre-blank[data-v-6667a46d]{color:#42b983} \ No newline at end of file diff --git a/assets/img/build-view-1.c8113aa8.png b/assets/img/build-view-1.c8113aa8.png new file mode 100644 index 0000000..f7d5de6 Binary files /dev/null and b/assets/img/build-view-1.c8113aa8.png differ diff --git a/assets/img/build-view-2.463cf913.png b/assets/img/build-view-2.463cf913.png new file mode 100644 index 0000000..73c80c2 Binary files /dev/null and b/assets/img/build-view-2.463cf913.png differ diff --git a/assets/img/file-lifecycle.b65dc1f4.png b/assets/img/file-lifecycle.b65dc1f4.png new file mode 100644 index 0000000..922b02c Binary files /dev/null and b/assets/img/file-lifecycle.b65dc1f4.png differ diff --git a/assets/img/git-vs-svn-1.ea94c3b2.png b/assets/img/git-vs-svn-1.ea94c3b2.png new file mode 100644 index 0000000..01d6adb Binary files /dev/null and b/assets/img/git-vs-svn-1.ea94c3b2.png differ diff --git a/assets/img/git-workflow-1.53c7ba82.png b/assets/img/git-workflow-1.53c7ba82.png new file mode 100644 index 0000000..7a73cca Binary files /dev/null and b/assets/img/git-workflow-1.53c7ba82.png differ diff --git a/assets/img/git-workflow-2.fa159868.png b/assets/img/git-workflow-2.fa159868.png new file mode 100644 index 0000000..7bce1d4 Binary files /dev/null and b/assets/img/git-workflow-2.fa159868.png differ diff --git a/assets/img/git-workflow-3.162afaf7.png b/assets/img/git-workflow-3.162afaf7.png new file mode 100644 index 0000000..ab41d2f Binary files /dev/null and b/assets/img/git-workflow-3.162afaf7.png differ diff --git a/assets/img/global-config-1.26650587.png b/assets/img/global-config-1.26650587.png new file mode 100644 index 0000000..3777148 Binary files /dev/null and b/assets/img/global-config-1.26650587.png differ diff --git a/assets/img/global-config-2.0e25eba0.png b/assets/img/global-config-2.0e25eba0.png new file mode 100644 index 0000000..6fb1313 Binary files /dev/null and b/assets/img/global-config-2.0e25eba0.png differ diff --git a/assets/img/global-config-3.f2fb0a68.png b/assets/img/global-config-3.f2fb0a68.png new file mode 100644 index 0000000..8cf1567 Binary files /dev/null and b/assets/img/global-config-3.f2fb0a68.png differ diff --git a/assets/img/global-config-5.5b0bb3ad.png b/assets/img/global-config-5.5b0bb3ad.png new file mode 100644 index 0000000..022ed13 Binary files /dev/null and b/assets/img/global-config-5.5b0bb3ad.png differ diff --git a/assets/img/global-config-6.0fbc7b60.png b/assets/img/global-config-6.0fbc7b60.png new file mode 100644 index 0000000..f0a77f0 Binary files /dev/null and b/assets/img/global-config-6.0fbc7b60.png differ diff --git a/assets/img/global-config-7.890edb2b.png b/assets/img/global-config-7.890edb2b.png new file mode 100644 index 0000000..491ddac Binary files /dev/null and b/assets/img/global-config-7.890edb2b.png differ diff --git a/assets/img/global-config-8.45d0ce81.png b/assets/img/global-config-8.45d0ce81.png new file mode 100644 index 0000000..91be0e7 Binary files /dev/null and b/assets/img/global-config-8.45d0ce81.png differ diff --git a/assets/img/global-config-9.eba1266a.png b/assets/img/global-config-9.eba1266a.png new file mode 100644 index 0000000..a1f9e14 Binary files /dev/null and b/assets/img/global-config-9.eba1266a.png differ diff --git a/assets/img/install-1.53b520eb.png b/assets/img/install-1.53b520eb.png new file mode 100644 index 0000000..5a750ab Binary files /dev/null and b/assets/img/install-1.53b520eb.png differ diff --git a/assets/img/install-2.d9fdfaf9.png b/assets/img/install-2.d9fdfaf9.png new file mode 100644 index 0000000..84c9739 Binary files /dev/null and b/assets/img/install-2.d9fdfaf9.png differ diff --git a/assets/img/install-bash-2.b92287a2.png b/assets/img/install-bash-2.b92287a2.png new file mode 100644 index 0000000..63f3c90 Binary files /dev/null and b/assets/img/install-bash-2.b92287a2.png differ diff --git a/assets/img/install-config-1.33f1dbb1.png b/assets/img/install-config-1.33f1dbb1.png new file mode 100644 index 0000000..271d674 Binary files /dev/null and b/assets/img/install-config-1.33f1dbb1.png differ diff --git a/assets/img/install-config-2.61b26b47.png b/assets/img/install-config-2.61b26b47.png new file mode 100644 index 0000000..0af07aa Binary files /dev/null and b/assets/img/install-config-2.61b26b47.png differ diff --git a/assets/img/install-done-1.06e95402.png b/assets/img/install-done-1.06e95402.png new file mode 100644 index 0000000..711028c Binary files /dev/null and b/assets/img/install-done-1.06e95402.png differ diff --git a/assets/img/install-done-2.353b0230.png b/assets/img/install-done-2.353b0230.png new file mode 100644 index 0000000..c93fbbf Binary files /dev/null and b/assets/img/install-done-2.353b0230.png differ diff --git a/assets/img/linux-file.cf47db04.jpg b/assets/img/linux-file.cf47db04.jpg new file mode 100644 index 0000000..493dd85 Binary files /dev/null and b/assets/img/linux-file.cf47db04.jpg differ diff --git a/assets/img/linux-mounting-1.aecba77b.png b/assets/img/linux-mounting-1.aecba77b.png new file mode 100644 index 0000000..3ed4ce0 Binary files /dev/null and b/assets/img/linux-mounting-1.aecba77b.png differ diff --git a/assets/img/linux-mounting-2.976e2351.png b/assets/img/linux-mounting-2.976e2351.png new file mode 100644 index 0000000..3f60d62 Binary files /dev/null and b/assets/img/linux-mounting-2.976e2351.png differ diff --git a/assets/img/linux-mounting-3.87609074.png b/assets/img/linux-mounting-3.87609074.png new file mode 100644 index 0000000..d916b04 Binary files /dev/null and b/assets/img/linux-mounting-3.87609074.png differ diff --git a/assets/img/pnpm_motivation_1.c8c32c46.jpg b/assets/img/pnpm_motivation_1.c8c32c46.jpg new file mode 100644 index 0000000..7b34e49 Binary files /dev/null and b/assets/img/pnpm_motivation_1.c8c32c46.jpg differ diff --git a/assets/img/pnpm_motivation_2.a23ee45d.jpg b/assets/img/pnpm_motivation_2.a23ee45d.jpg new file mode 100644 index 0000000..b3aafc7 Binary files /dev/null and b/assets/img/pnpm_motivation_2.a23ee45d.jpg differ diff --git a/assets/img/post-proccess-1.3e5d2236.png b/assets/img/post-proccess-1.3e5d2236.png new file mode 100644 index 0000000..9c3d833 Binary files /dev/null and b/assets/img/post-proccess-1.3e5d2236.png differ diff --git a/assets/img/reset-pwd.8c11753b.png b/assets/img/reset-pwd.8c11753b.png new file mode 100644 index 0000000..5a7c0ef Binary files /dev/null and b/assets/img/reset-pwd.8c11753b.png differ diff --git a/assets/img/search.83621669.svg b/assets/img/search.83621669.svg new file mode 100644 index 0000000..03d8391 --- /dev/null +++ b/assets/img/search.83621669.svg @@ -0,0 +1 @@ + diff --git a/assets/img/simplify-dp.aa401773.gif b/assets/img/simplify-dp.aa401773.gif new file mode 100644 index 0000000..a73ac1f Binary files /dev/null and b/assets/img/simplify-dp.aa401773.gif differ diff --git a/assets/img/simplify-vw.d2ad01c4.jpg b/assets/img/simplify-vw.d2ad01c4.jpg new file mode 100644 index 0000000..38ad963 Binary files /dev/null and b/assets/img/simplify-vw.d2ad01c4.jpg differ diff --git a/assets/img/system-config-1.2af55165.png b/assets/img/system-config-1.2af55165.png new file mode 100644 index 0000000..47182b6 Binary files /dev/null and b/assets/img/system-config-1.2af55165.png differ diff --git a/assets/js/10.2d4dac3b.js b/assets/js/10.2d4dac3b.js new file mode 100644 index 0000000..a27aae5 --- /dev/null +++ b/assets/js/10.2d4dac3b.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[10],{265:function(t,s,n){t.exports=n.p+"assets/img/pnpm_motivation_1.c8c32c46.jpg"},266:function(t,s,n){t.exports=n.p+"assets/img/pnpm_motivation_2.a23ee45d.jpg"},313:function(t,s,n){"use strict";n.r(s);var a=n(13),p=Object(a.a)({},(function(){var t=this,s=t._self._c;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"pnpm"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#pnpm"}},[t._v("#")]),t._v(" pnpm")]),t._v(" "),s("h2",{attrs:{id:"_1-npmp简介"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#_1-npmp简介"}},[t._v("#")]),t._v(" 1. npmp简介")]),t._v(" "),s("h3",{attrs:{id:"_1-1-pnpm特点"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#_1-1-pnpm特点"}},[t._v("#")]),t._v(" 1.1 pnpm特点")]),t._v(" "),s("ul",[s("li",[s("p",[s("mark",[t._v("【无痛切换】")]),t._v("与"),s("code",[t._v("npm")]),t._v("/"),s("code",[t._v("yarn")]),t._v("等主流包管理工具的使用类似,易于上手")])]),t._v(" "),s("li",[s("p",[s("mark",[t._v("【节省磁盘空间并提升安装速度】")]),t._v("采用"),s("code",[t._v("统一的包管理目录")]),t._v("对机器所安装的所有包进行管理")]),t._v(" "),s("ul",[s("li",[t._v("项目需要依赖时首先会去该目录下检索,存在则复用,没有则新添加至统一包管理目录;")]),t._v(" "),s("li",[t._v("如果是相同的依赖但不同版本时,只会检索该依赖下不同的依赖进行添加;")])])]),t._v(" "),s("li",[s("p",[s("mark",[t._v("【非扁平的 node_modules 目录】")]),t._v("依赖使用"),s("code",[t._v("硬链接(hard-link)")]),t._v("和"),s("code",[t._v("符号链接(symbolic link)")]),t._v("进行相互关联")]),t._v(" "),s("ul",[s("li",[t._v("在项目的"),s("code",[t._v("node_modules")]),t._v("目录中存在"),s("code",[t._v(".pnpm")]),t._v("目录,以及同级的、使用符号连接的依赖目录")]),t._v(" "),s("li",[s("code",[t._v(".pnpm")]),t._v("目录下面的部分依赖"),s("u",[t._v("硬链接")]),t._v("至"),s("code",[t._v("统一包管理目录")]),t._v(",而"),s("code",[t._v(".pnpm")]),t._v("目录同级的以来则是使用"),s("u",[t._v("符号链接")]),t._v("对依赖进行引用")])])]),t._v(" "),s("li",[s("p",[s("mark",[t._v("【多栖环境】")]),t._v("pnpm可以不需要对node的环境有太多依赖,因为自身可以设置使用node的具体版本")])])]),t._v(" "),s("p",[s("img",{attrs:{src:n(265),alt:"节省磁盘空间并提升安装速度",title:"节省磁盘空间并提升安装速度"}}),t._v(" "),s("img",{attrs:{src:n(266),alt:"非扁平的node_modules目录",title:"非扁平的node_modules目录"}})]),t._v(" "),s("h3",{attrs:{id:"_1-2-pnpm与npm-yarn的区别-优势-1-2"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#_1-2-pnpm与npm-yarn的区别-优势-1-2"}},[t._v("#")]),t._v(" 1.2 pnpm与npm/yarn的区别(优势)"),s("sup",[t._v("1,2")])]),t._v(" "),s("ul",[s("li",[t._v("相比"),s("code",[t._v("npm2")]),t._v(" ,"),s("code",[t._v("pnpm")]),t._v("不会进行同样依赖的多次复制")]),t._v(" "),s("li",[t._v("相比"),s("code",[t._v("yarn")]),t._v("以及"),s("code",[t._v("npm3+")]),t._v(",不会有幽灵依赖(幽灵依赖是由于依赖声明丢失造成的)和,也不会有依赖分身(没有被提升的依赖依然复制多份)\\")])]),t._v(" "),s("h3",{attrs:{id:"_1-3-pnpm的弊端2"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#_1-3-pnpm的弊端2"}},[t._v("#")]),t._v(" 1.3 pnpm的弊端"),s("sup",[t._v("2")])]),t._v(" "),s("ul",[s("li",[t._v("无法在不支持软连接的环境中使用"),s("code",[t._v("pnpm")]),t._v(",比如"),s("code",[t._v("Electron")]),t._v("应用")]),t._v(" "),s("li",[t._v("因为依赖安装在"),s("code",[t._v("统一的包管理目录")]),t._v("中的,调试依赖或使用"),s("code",[t._v("patch-package")]),t._v("给依赖打补丁不方便,可能会影响到其他项目")])]),t._v(" "),s("h2",{attrs:{id:"_2-安装与配置"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#_2-安装与配置"}},[t._v("#")]),t._v(" 2. 安装与配置")]),t._v(" "),s("ul",[s("li",[s("p",[t._v("安装")]),t._v(" "),s("div",{staticClass:"language-sh extra-class"},[s("pre",{pre:!0,attrs:{class:"language-sh"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# 安装(一般全局安装)")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("npm")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("install")]),t._v(" -g "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("pnpm")]),t._v("\n")])])])]),t._v(" "),s("li",[s("p",[t._v("配置")]),t._v(" "),s("ul",[s("li",[s("p",[s("strong",[t._v("node环境设置")])]),t._v(" "),s("p",[t._v("pnpm支持在没有node(npm)的环境下进行"),s("a",{attrs:{href:"https://www.pnpm.cn/installation",target:"_blank",rel:"noopener noreferrer"}},[t._v("安装"),s("OutboundLink")],1),t._v("。\n安装完成后,可以使用"),s("code",[t._v("pnpm env")]),t._v("指令对node版本进行设置")]),t._v(" "),s("div",{staticClass:"language-sh extra-class"},[s("pre",{pre:!0,attrs:{class:"language-sh"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# 全局使用最新node版本")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("pnpm")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("env")]),t._v(" use --global lts\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# 全局使用具体node版本号的版本")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("pnpm")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("env")]),t._v(" use --global xx.xx.x\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# 全局使用预发布版本")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("pnpm")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("env")]),t._v(" use --global nightly\n"),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("pnpm")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("env")]),t._v(" use --global rc\n"),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("pnpm")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("env")]),t._v(" use --global "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("16.0")]),t._v(".0-rc.0\n"),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("pnpm")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("env")]),t._v(" use --global rc/14\n")])])])]),t._v(" "),s("li",[s("p",[s("strong",[t._v("统一存储目录(内容寻址目录)")])]),t._v(" "),s("ul",[s("li",[t._v("自动生成\n会自动在当前磁盘分区的根目录生成"),s("code",[t._v(".pnmp-store")]),t._v("目录")]),t._v(" "),s("li",[t._v("手动生成")])]),t._v(" "),s("div",{staticClass:"language-sh extra-class"},[s("pre",{pre:!0,attrs:{class:"language-sh"}},[s("code",[s("span",{pre:!0,attrs:{class:"token function"}},[t._v("pnpm")]),t._v(" config "),s("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v("set")]),t._v(" store-dir "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("path"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("/.pnpm-store\n")])])])]),t._v(" "),s("li",[s("p",[s("strong",[t._v("镜像")])]),t._v(" "),s("div",{staticClass:"language-sh extra-class"},[s("pre",{pre:!0,attrs:{class:"language-sh"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# 查看镜像")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("pnpm")]),t._v(" config get registry \n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# 切换镜像(淘宝镜像)")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("pnpm")]),t._v(" config "),s("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v("set")]),t._v(" registry https://registry.npmmirror.com/\n")])])])]),t._v(" "),s("li",[s("p",[s("strong",[t._v("环境变量(Path)+全局指令目录(global-bin-dir)")])]),t._v(" "),s("ul",[s("li",[s("p",[t._v("自动配置环境")]),t._v(" "),s("div",{staticClass:"language-sh extra-class"},[s("pre",{pre:!0,attrs:{class:"language-sh"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# 自动配置环境变量")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("pnpm")]),t._v(" setup\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# 设置全局bin文件目录")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("pnpm")]),t._v(" config "),s("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v("set")]),t._v(" global-bin-dir "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("path"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("/.pnpm-global-bin-dir\n")])])])]),t._v(" "),s("li",[s("p",[t._v("手动设置")]),t._v(" "),s("ul",[s("li",[s("p",[t._v("Windows")]),t._v(" "),s("ol",[s("li",[t._v("设置变量:"),s("code",[t._v("PNPM_HOME")]),t._v(",变量值:"),s("code",[t._v("{path}/.pnpm-global-bin-dir")])]),t._v(" "),s("li",[t._v("变量该添加至Path中:"),s("code",[t._v("%PNPM_HOME%")])]),t._v(" "),s("li",[t._v("设置全局bin文件目录:")])]),t._v(" "),s("div",{staticClass:"language-sh extra-class"},[s("pre",{pre:!0,attrs:{class:"language-sh"}},[s("code",[s("span",{pre:!0,attrs:{class:"token function"}},[t._v("pnpm")]),t._v(" config "),s("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v("set")]),t._v(" global-bin-dir "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("path"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("/.pnpm-global-bin-dir\n")])])])]),t._v(" "),s("li",[s("p",[t._v("Linux")]),t._v(" "),s("p",[s("code",[t._v("TODO...")])])])])])])])])])]),t._v(" "),s("h2",{attrs:{id:"_3-常用-cli-操作"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#_3-常用-cli-操作"}},[t._v("#")]),t._v(" 3. 常用 CLI 操作")]),t._v(" "),s("p",[t._v("对项目/依赖的相关操作与"),s("code",[t._v("npm")]),t._v("/"),s("code",[t._v("yarn")]),t._v("类似")]),t._v(" "),s("h3",{attrs:{id:"_3-1-添加-移除-更新"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#_3-1-添加-移除-更新"}},[t._v("#")]),t._v(" 3.1 添加/移除/更新")]),t._v(" "),s("div",{staticClass:"language-sh extra-class"},[s("pre",{pre:!0,attrs:{class:"language-sh"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# []表示可替换选项,其中/分隔为选项可选")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# 表示相应的依赖包名称")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# 安装项目所有依赖")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("pnpm")]),t._v(" install"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("i"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# 安装-全局依赖(从全局环境中添加指定的软件包)")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("pnpm")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),t._v(" -g"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("--global"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v("pkg"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# 安装-开发依赖(添加至devDependencies配置项)")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("pnpm")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),t._v(" -D"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("--save-dev"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v("pkg"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# 安装-生产依赖(添加至dependencies配置项)")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("pnpm")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("-P/--save-prod"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v("pkg"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# 删除-全局依赖(从全局环境中删除指定的软件包)")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("pnpm")]),t._v(" remove"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("rm/uninstall/un"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" -g"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("--global"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v("pkg"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# 删除-开发依赖(从devDependencies配置项中移除)")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("pnpm")]),t._v(" remove"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("rm/uninstall/un"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" -D"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("--save-dev"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v("pkg"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# 删除-生产依赖(从dependencies配置项中移除)")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("pnpm")]),t._v(" remove"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("rm/uninstall/un"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("-P/--save-prod"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v("pkg"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# 更新-全局依赖")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("pnpm")]),t._v(" update"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("up"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" -g"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("--global"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v("pkg"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# 更新-开发依赖")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("pnpm")]),t._v(" update"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("up"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" -D"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("--dev"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v("pkg"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# 更新-生产依赖")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("pnpm")]),t._v(" update"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("up"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" -P"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("--prod"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v("pkg"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v("\n")])])]),s("h3",{attrs:{id:"_3-2-清理"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#_3-2-清理"}},[t._v("#")]),t._v(" 3.2 清理")]),t._v(" "),s("p",[t._v("删除不需要的软件包,"),s("mark",[s("strong",[t._v("不建议经常执行该指令")])])]),t._v(" "),s("div",{staticClass:"language-sh extra-class"},[s("pre",{pre:!0,attrs:{class:"language-sh"}},[s("code",[s("span",{pre:!0,attrs:{class:"token function"}},[t._v("pnpm")]),t._v(" prune\n")])])]),s("h3",{attrs:{id:"_3-3-运行脚本"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#_3-3-运行脚本"}},[t._v("#")]),t._v(" 3.3 运行脚本")]),t._v(" "),s("div",{staticClass:"language-sh extra-class"},[s("pre",{pre:!0,attrs:{class:"language-sh"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# + + diff --git a/dev_frontend/js_es6.html b/dev_frontend/js_es6.html new file mode 100644 index 0000000..2edef61 --- /dev/null +++ b/dev_frontend/js_es6.html @@ -0,0 +1,35 @@ + + + + + + ES6 | kite-notes + + + + + + + + + +

# ES6

# 新特性

  • var let const
  • 箭头函数
  • rest spread 操作符 ...
  • 解构赋值: +
    • 对象:属性读取,变量重命名,函数传参
  • 数组:元素获取,rest子数组
  • 模板字符串
  • 简化字面量声明:属性名与变量名相同时,可不写变量名
  • 简化函数声明:对象中可以不写function关键字
  • class constructor get set
  • export +
    • export {} (命名导出)
    • expport default {} (命名/匿名导出)
  • import +
    • import {} from (命名导出-导入)
    • import * as xxx from (命名导出-导入)
    • import xxx from (默认导出-导入方式)
  • Promise +
    • 状态(pending、fulfilled 和 rejected)
    • 参数(resolve 和 reject)-> 结束Promise
    • then catch
+ + + diff --git a/dev_frontend/js_polling.html b/dev_frontend/js_polling.html new file mode 100644 index 0000000..94808e1 --- /dev/null +++ b/dev_frontend/js_polling.html @@ -0,0 +1,31 @@ + + + + + + 轮询 | kite-notes + + + + + + + + + +
+ + + diff --git a/dev_frontend/js_throttle_debounce.html b/dev_frontend/js_throttle_debounce.html new file mode 100644 index 0000000..23e0b7e --- /dev/null +++ b/dev_frontend/js_throttle_debounce.html @@ -0,0 +1,135 @@ + + + + + + 节流&防抖 | kite-notes + + + + + + + + + +

# 节流&防抖

节流和防抖主要是为了优化前端的因多次回调导致性能下降问题以及减少后端请求处理压力。常用于短时间内触发重复事件的处理逻辑。

节流:在一定时间内只发起第一次调用,之后的具体时间段内,无视对其回调函数重复调用

防抖:在计时开始/结束后调用,若在一定时间内重复触发,则重新计时,直到最后一次调用

# 节流

节流有三种实现方式,时间戳定时器以及两者的结合

常见场景:

  1. 事件回调处理,如鼠标移动事件mousemove、窗口大小改变事件resize
/**
+ * 时间戳实现节流
+ * @param {Function} fn 回调函数
+ * @param {Number} delay 允许时长
+ * @returns {Function} 
+ */
+function throttleByTimeStamp(fn, delay) {
+  var timeOld = +Date.now();
+
+  return function () {
+    var timeNew = +Date.now();
+    if (timeNew - timeOld >= delay) {
+      fn.apply(this, arguments);
+      timeOld = +Date.now();
+    }
+  };
+}
+
+/**
+ * 计时器实现节流
+ * @param {Function} fn 回调函数
+ * @param {Number} delay 允许时长
+ * @returns {Function}
+ */
+function throttleByTimer(fn, delay) {
+  var timer = null;
+
+  return function () {
+    if (!timer) {
+      timer = setTimeout(function () {
+        fn.apply(this, arguments);
+        timer = null;
+      }, delay);
+    }
+  };
+}
+
+document.addEventListener(
+  "mousemove",
+  // 测试-时间戳实现
+  // throttleByTimeStamp(function (res) {
+  //   console.log(+Date.now());
+  // }, 1000)
+  // 测试-定时器实现
+  throttleByTimer(function (res) {
+    console.log(+Date.now());
+  }, 1000)
+);
+

# 防抖

防抖主要应用在一些经过连续操作结束后,只处理一次回调的场景,如<input><button>处理。

常见场景:

  1. 搜索输入框的动态索引(如谷歌搜索引擎)
  2. 重复点击提交表单按钮

主要的实现方式是使用定时器,但有时候也会出现防抖需要立即执行的情况

/**
+ * 延迟执行
+ * @param {Function} fn 回调函数
+ * @param {Number} delay 延迟时长
+ * @returns {Function}
+ */
+function debounce(fn, delay) {
+  var timeout = null;
+
+  return function () {
+    var ctx = this;
+    var args = arguments;
+    // 每次出发回调就会清除掉上一次的计时器,并重新定义生成器
+    clearTimeout(timeout);
+
+    timeout = setTimeout(function () {
+      fn.apply(ctx, args);
+    }, delay);
+  };
+}
+
+/**
+ * 立即执行
+ * @param {Function} fn 回调函数
+ * @param {Number} delay 延迟时长
+ * @param {Boolean} immediate 是否立即执行
+ * @returns {Function}
+ */
+function debounceImmediate(fn, delay, immediate) {
+  var timeout = null;
+
+  return function () {
+    var ctx = this;
+    var args = arguments;
+
+    // 清除掉上一次的计时器
+    if (timeout) {
+      clearTimeout();
+    }
+    if (immediate) {
+      var callNow = !timeout; // timeout为空则立即执行
+      // 随后将计时器置空(重新开始)
+      timeout = setTimeout(function () {
+        timeout = null;
+      }, delay);
+
+      if (callNow) {
+        fn.apply(ctx, args);
+      }
+    } else {
+      timeout = setTimeout(function () {
+        fn.apply(ctx, args);
+      }, delay);
+    }
+  };
+}
+

# 两者的联系与区别

联系:

  1. 节流和防抖都是为了减轻前端处理性能压力(回调函数的执行频率),节省资源开销
  2. 节流和防抖都可以通过setTimeout实现

区别:

  1. 节流:在一段时间内的连续操作,只执行一次回调
  2. 防抖:在一段时间内的连续操作,只执行最后一次回调(通过setTimeoutclearTimeout实现)
+ + + diff --git a/dev_frontend/js_utils.html b/dev_frontend/js_utils.html new file mode 100644 index 0000000..80ea2f4 --- /dev/null +++ b/dev_frontend/js_utils.html @@ -0,0 +1,38 @@ + + + + + + JavaScript 常用操作 | kite-notes + + + + + + + + + +

# JavaScript 常用操作

# 随机数生成

生成随机数主要使用的是Math.random()方法,**返回0(包括0)到1(不包括1)**的小数。

  • 生成随机小数(分数)
Math.random()
+
  • 生成指定范围的随机整数(0至***)
Math.floor(Math.random() * 10) // 0-9
+
  • 生成指定范围的随机整数(最小范围至最大范围)
/**
+ * max: 最大值
+ * min:最小值
+ */
+Math.floor(Math.random() * (max - min + 1) + min)
+
+ + + diff --git a/dev_frontend/tool_pnpm.html b/dev_frontend/tool_pnpm.html new file mode 100644 index 0000000..f39d498 --- /dev/null +++ b/dev_frontend/tool_pnpm.html @@ -0,0 +1,85 @@ + + + + + + pnpm | kite-notes + + + + + + + + + +

# pnpm

# 1. npmp简介

# 1.1 pnpm特点

  • 【无痛切换】npm/yarn等主流包管理工具的使用类似,易于上手

  • 【节省磁盘空间并提升安装速度】采用统一的包管理目录对机器所安装的所有包进行管理

    • 项目需要依赖时首先会去该目录下检索,存在则复用,没有则新添加至统一包管理目录;
    • 如果是相同的依赖但不同版本时,只会检索该依赖下不同的依赖进行添加;
  • 【非扁平的 node_modules 目录】依赖使用硬链接(hard-link)符号链接(symbolic link)进行相互关联

    • 在项目的node_modules目录中存在.pnpm目录,以及同级的、使用符号连接的依赖目录
    • .pnpm目录下面的部分依赖硬链接统一包管理目录,而.pnpm目录同级的以来则是使用符号链接对依赖进行引用
  • 【多栖环境】pnpm可以不需要对node的环境有太多依赖,因为自身可以设置使用node的具体版本

节省磁盘空间并提升安装速度 非扁平的node_modules目录

# 1.2 pnpm与npm/yarn的区别(优势)1,2

  • 相比npm2pnpm不会进行同样依赖的多次复制
  • 相比yarn以及npm3+,不会有幽灵依赖(幽灵依赖是由于依赖声明丢失造成的)和,也不会有依赖分身(没有被提升的依赖依然复制多份)\

# 1.3 pnpm的弊端2

  • 无法在不支持软连接的环境中使用pnpm,比如Electron应用
  • 因为依赖安装在统一的包管理目录中的,调试依赖或使用patch-package给依赖打补丁不方便,可能会影响到其他项目

# 2. 安装与配置

  • 安装

    # 安装(一般全局安装)
    +npm install -g pnpm
    +
  • 配置

    • node环境设置

      pnpm支持在没有node(npm)的环境下进行安装 (opens new window)。 +安装完成后,可以使用pnpm env指令对node版本进行设置

      # 全局使用最新node版本
      +pnpm env use --global lts
      +# 全局使用具体node版本号的版本
      +pnpm env use --global xx.xx.x
      +# 全局使用预发布版本
      +pnpm env use --global nightly
      +pnpm env use --global rc
      +pnpm env use --global 16.0.0-rc.0
      +pnpm env use --global rc/14
      +
    • 统一存储目录(内容寻址目录)

      • 自动生成 +会自动在当前磁盘分区的根目录生成.pnmp-store目录
      • 手动生成
      pnpm config set store-dir {path}/.pnpm-store
      +
    • 镜像

      # 查看镜像
      +pnpm config get registry 
      +# 切换镜像(淘宝镜像)
      +pnpm config set registry https://registry.npmmirror.com/
      +
    • 环境变量(Path)+全局指令目录(global-bin-dir)

      • 自动配置环境

        # 自动配置环境变量
        +pnpm setup
        +# 设置全局bin文件目录
        +pnpm config set global-bin-dir {path}/.pnpm-global-bin-dir
        +
      • 手动设置

        • Windows

          1. 设置变量:PNPM_HOME,变量值:{path}/.pnpm-global-bin-dir
          2. 变量该添加至Path中:%PNPM_HOME%
          3. 设置全局bin文件目录:
          pnpm config set global-bin-dir {path}/.pnpm-global-bin-dir
          +
        • Linux

          TODO...

# 3. 常用 CLI 操作

对项目/依赖的相关操作与npm/yarn类似

# 3.1 添加/移除/更新

# []表示可替换选项,其中/分隔为选项可选
+# <pkg>表示相应的依赖包名称
+
+# 安装项目所有依赖
+pnpm install[i]
+
+# 安装-全局依赖(从全局环境中添加指定的软件包)
+pnpm add -g[--global] <pkg>
+# 安装-开发依赖(添加至devDependencies配置项)
+pnpm add -D[--save-dev] <pkg>
+# 安装-生产依赖(添加至dependencies配置项)
+pnpm add [-P/--save-prod] <pkg>
+
+# 删除-全局依赖(从全局环境中删除指定的软件包)
+pnpm remove[rm/uninstall/un] -g[--global] <pkg>
+# 删除-开发依赖(从devDependencies配置项中移除)
+pnpm remove[rm/uninstall/un] -D[--save-dev] <pkg>
+# 删除-生产依赖(从dependencies配置项中移除)
+pnpm remove[rm/uninstall/un] [-P/--save-prod] <pkg>
+
+# 更新-全局依赖
+pnpm update[up] -g[--global] <pkg>
+# 更新-开发依赖
+pnpm update[up] -D[--dev] <pkg>
+# 更新-生产依赖
+pnpm update[up] -P[--prod] <pkg>
+

# 3.2 清理

删除不需要的软件包,不建议经常执行该指令

pnpm prune
+

# 3.3 运行脚本

# <script>是项目package.json中的script脚本
+
+pnpm run <script>
+pnpm <script> # 简写(前提是脚本与pnpm内建指令不冲突)
+

# 参考文档

  1. pnpm 是凭什么对 npm 和 yarn 降维打击的 (opens new window)

  2. 深入浅出 npm & yarn & pnpm 包管理机制 (opens new window)

+ + + diff --git a/dev_gis/algo_simplify.html b/dev_gis/algo_simplify.html new file mode 100644 index 0000000..62f1686 --- /dev/null +++ b/dev_gis/algo_simplify.html @@ -0,0 +1,31 @@ + + + + + + 「算法」抽稀(概化) | kite-notes + + + + + + + + + +

# 「算法」抽稀(概化)

# 背景/应用场景

随着对海量地理空间数据加载、渲染的需求日益增加。在地理信息系统中,对一些细节程度高的数据在地图上的展示往往需要绘制大量的坐标点,当地图缩放层级较小时,并不需要将所有的点都绘制出来,因为全部绘制出来往往会存在性能问题,因此,可通过抽稀算法,将不重要的点舍弃掉,那么系统对矢量数据加载的处理性能将得以提高,同时不影响视觉效果。

# 抽稀算法类型

抽稀,也称作概化。抽稀算法的关键是定义抽稀因子,抽稀因子的不同决定了抽稀算法的多样性。在现有抽稀理论中,有按步长,线段长度,垂距等来定义抽稀因子。1在GIS领域,比较常用的抽稀算法是Ramer-Douglas-Peucker算法(基于距离)和Visvalingam-Whyatt算法(基于面积)。

# Ramer-Douglas-Peucker(道格拉斯-普克)

从整体角度来考虑一条完整曲线或一段具体线段,思路为:

  1. 确定距离阈值D,即抽稀因子,作为判断是否抽稀的指标
  2. 对曲线的首末两点虚连一条直线,计算曲线每个点到虚直线的距离,找到最大距离Dmax,判断其距离与距离阈值D的关系
  3. 如果Dmax < D,则舍弃该曲线的所有中间点,将虚直线作为抽稀后的线段
  4. 如果Dmax >= D,则找到Dmax在曲线上的对应的点作为分割点将当前曲线分割为两段,继续对这两条线段进行第2步操作(即递归处理,直至所有Dmax < D,则处理完毕)

Ramer-Douglas-Peucker思路可视化

上图说明(可对应思路说明进行理解):

  • 黑色曲线:表示抽稀前的曲线
  • 浅蓝色直线:表示虚直线
  • 深蓝色直线:表示抽稀后的曲线
  • 最大值对应点(红色):表示Dmax < D,可以舍弃该曲线的所有中间点
  • 最大值对应点(绿色):表示Dmax >= D,需要进行曲线分割并重新处理

# Visvalingam-Whyatt

是一种渐进式的抽稀方式,思路为:

  1. 确定距离阈值A,即抽稀因子,作为判断是否抽稀的指标
  2. 在一条曲线中,计算由三个连续的点所形成三角形面积,找到这些三角中的最小面积Amin,判断其面积与面积阈值A的关系
  3. 如果Amin < A,则删除该面积对应三角形中的中间顶点,继续对剩下的顶点所形成的曲线进行第2步操作(即递归处理,直至所有Amin > A,则处理完毕)

Visvalingam-Whyatt思路可视化

# Ramer-Douglas-Peucker和Visvalingam-Whyatt的算法区别

  1. Ramer-Douglas-Peucker算法的优点是计算简单,但它的结果可能会出现自相交
  2. Ramer-Douglas-Peucker计算效率更高,它的时间复杂度是O(n^2)Visvalingam-Whyatt的时间复杂度是O(n·log(n))
  3. Ramer-Douglas-Peucker算法的阈值是距离,Visvalingam-Whyatt算法的阈值是面积
  4. 相比起Ramer-Douglas-Peucker算法的选取保留点,Visvalingam-Whyatt算法是选取删除点
  5. 相比起Ramer-Douglas-Peucker算法,Visvalingam-Whyatt算法产生的角度变化更小,更能保留几何面的特征,更加适用于河流、森林或海岸线等自然线条或多边形特征的抽稀

# 拓扑问题

概化数据可能会破坏数据的拓扑关系,因此,可以先将数据转化为拓扑结构,再对拓扑数据进行数据概化(抽稀)

# 实现

# 已有实现

  1. mapshaper -simlpify (opens new window)
  2. Simply.js (opens new window)
  3. OpenpLayers —— ol/geom/Geometry -> simplify(tolerance) (opens new window)
  4. QGIS —— MenuBar -> Vector -> Geometry Tools -> Simplify
  5. QGIS —— ToolBox-> GRass -> Vector -> v.generalize

# 参考文档

  1. 抽稀-百度百科 (opens new window)

  2. 空间数据量大怎么办,三种方式告诉你怎么抽稀 (opens new window)

  3. 常用的地图数据概化算法:Douglas-Peucker与Visvalingam-Whyatt (opens new window)

  4. Description of Visvalingam & Whyatt Line Simplification Algorithm (opens new window)

+ + + diff --git a/dev_gis/esri_arcgis_server.html b/dev_gis/esri_arcgis_server.html new file mode 100644 index 0000000..d0867f6 --- /dev/null +++ b/dev_gis/esri_arcgis_server.html @@ -0,0 +1,33 @@ + + + + + + 「ESRI」ArcGIS Server | kite-notes + + + + + + + + + +

# 「ESRI」ArcGIS Server

# Export Map

# 应用场景

  1. 地图图片的导出/获取。根据地理坐标范围,向地图服务发起请求获取响应格式的地图
  2. 系统底图的加载。本质是地图图片的获取。根据屏幕坐标与实际地理坐标的转换,得到当前地图视图的坐标范围,再向地图服务发起请求

# 请求

  • 请求路由:/export
  • 请求方式:GET/POST
  • 请求参数(详见API文档 (opens new window)) +
    参数
    (⭐️表示常用)
    说明
    ⭐️bbox 边界范围(坐标范围)
    ⭐️bboxSR 边界范围的空间参考,支持WKT代号ID或具体空间参考定义文本,不定义则默认使用地图服务的空间参考
    ⭐️layers 需要导出的图层索引
    show:展示的图层索引
    hide:隐藏的图层索引
    include:包括的图层索引
    exclude:排除的图层索引
    layerDef 图层过滤定义
    ⭐️size 导出地图的像素大小,默认为400,400
    ⭐️imgSR 导出图片的空间参考,同bboxSR
    ⭐️format 导出图片的格式,默认为png
    ⭐️transparent 背景是否透明,默认为false
    dpi 导出图片的分辨率,默认为96
    time 导出的地图图像的时间瞬间或时间范围
    layerTimeOptions 指定图层的时间定义
    dynamicLayers 动态图层定义
    gdbVersion 指定查询的地理数据库的版本,当不指定时,则默认使用发布地图服务时使用的版本
    mapScale 地图的比例尺
    f 请求返回的格式,默认是html

# Query

# 应用场景

  1. 属性查询(属性查图)。类似普通的数据库查询,但可以返回属性信息,选择性返回空间信息
  2. 空间查询(图查属性)。与属性查询类似,使用空间过滤条件查询对应的属性信息/空间信息
  3. 快速的空间操作。快速进行空间操作(如裁剪、合并、擦除...)获取用户所需的信息

# 请求

  • 请求路由:/query
  • 请求方式:GET/POST
  • 请求参数(详见API文档 (opens new window)) +
    参数
    (⭐️表示常用)
    说明
    ⭐️where 属性查询SQL的where子句
    text displayField的值查询(支持模糊查询)。
    形成的查询Where子句:<displayField> like '<text>'
    当指定where参数后,该参数会被忽略
    objectIds 查询指定ObjectID的属性
    time 限制查询的时间瞬间或时间范围,常用于有时间尺度的地理数据(时空数据)
    ⭐️geometry 空间过滤-几何图形
    ⭐️geometryType 空间过滤-几何图形类
    esriGeometryPoint:点
    esriGeometryMultipoint:多点
    esriGeometryPolyline:折线
    esriGeometryPolygon:多边形
    esriGeometryEnvelope:外包矩形(默认值)
    ⭐️inSR 空间过滤-几何图像-空间参考,支持WKT代号ID或具体空间参考定义文本,不定义则默认使用地图服务的空间参考
    ⭐️spatialRel 空间过滤-对输入的geometry的空间关系查询
    relationParam 属性查询SQL的where子句
    ⭐️outFields 输出的字段
    returnGeometry 是否返回几何图形,默认为true
    maxAllowableOffset 最大允许误差范围,根据单位由inSR确定,若没有inSR,则使用该地图的空间参考
    geometryPrecision 返回几何图形的精度,具体指的是坐标点的小数点位数(只支持XY坐标,M和Z值不支持)
    ⭐️outSR 输出的几何图形的空间参考定义,支持WKT代号ID或具体空间参考定义文本,不定义则默认使用地图服务的空间参考
    returnIdsOnly 是否值只返回ObjectId数组,不返回要素集,默认为false
    returnCountOnly 是否只返回数量(通过count函数计算查询结果要素集中要素的数量),默认为false
    orderByFields 根据一个或多个字段进行排序,需要指定排序方式,否则默认采用升序(ASC)
    需要地图服务支持高级查询(supportsAdvancedQueries
    groupByFieldsForStatistics 一个或多个用于分组统计的字段
    outStatistics 基于(字段)对象字面量数组配置进行分组统计
    需要地图服务支持统计查询(suppportsStatistics
    returnZ 是否返回Z值(高程值),默认为false
    returnM 是否返回M值(测量值),默认为false
    gdbVersion 指定查询的地理数据库的版本,当不指定时,则默认使用发布地图服务时使用的版本
    returnDistinctValues 是否基于outField参数返回指定的字段的唯一值(去重),默认为false
+ + + diff --git a/dev_gis/index.html b/dev_gis/index.html new file mode 100644 index 0000000..e50cb22 --- /dev/null +++ b/dev_gis/index.html @@ -0,0 +1,23 @@ + + + + + + 开发技巧-GIS | kite-notes + + + + + + + + + +
+ + + diff --git a/dev_gis/interview_3d_gis.html b/dev_gis/interview_3d_gis.html new file mode 100644 index 0000000..610ada8 --- /dev/null +++ b/dev_gis/interview_3d_gis.html @@ -0,0 +1,28 @@ + + + + + + 三维GIS开发工程师 | kite-notes + + + + + + + + + +

# 三维GIS开发工程师

# OpenLayers如何加载ArcGIS地图服务

WebGIS中,客户端展示地图专题的主要方式是动态展示地图(根据范围等属性生成对应的地图图片)和瓦片影像(根据切片规则生成的瓦片数据)

OpenLayers根据以上两种方式提供了两种数据源ol/source/TileArcGISRest (opens new window)ol/source/ImageArcGISRest (opens new window)。除了基础的属性如urlprojection,还需要重点关注其加载函数tileLoadFunction/imageLoadFunction,其能过够定制化一些业务处理逻辑,也能够控制地图请求的状态,如ol/TileState

至于如何加载ArcGIS地图服务,只需要根据地图服务的类型,选择OpenLayers合适的数据源类(source),使用对应的图层类(layer)对其包裹,最终便可在地图(map)和视图(view)中显示。

# OpenLayers常用坐标系是什么?是否支持坐标系转换?

一般来说,互联网中地图通用的地理坐标系统是WGS84坐标系(ESPG:3857ESPG:4326)。因此OpenLayers也将该两个坐标系作为默认坐标系,但是OpenLayers提供了额外的坐标系定义类ol/proj/Projection (opens new window)。定义好后则可以支持已有坐标系的互转

# Cesium如何加载ArcGIS地图服务

OpenLayers的图层加载类似,需要一个图层实例(ImageryProvider)及其内部的数据源(Cesium.***ImageryProvider

对于ArcGIS地图服务来说,主要是:

  1. 通用WebMapServiceImageryProvider(加载WMS服务,除ArcGIS之外也支持其他厂商的地图服务加载)
  2. 通用WebMapTileServiceImageryProvider(加载WMTS服务,支持KVP和RESTful格式)
  3. Cesium提供的ArcGIS用数据源类ArcGisMapServerImageryProvider(加载WMTS服务)
  4. ArcGISTiledElevationTerrainProvider(加载地形服务)

最终,对于一般的地图服务(如WMS服务、WMTS服务),可以通过ImageryLayerCollection收集所有***ImageryProvider,并设置到ViewerimageryLayers属性中(其实也是Viewerscene属性的global属性的imageryLayers属性)。对于地形服务,则通过将ArcGISTiledElevationTerrainProvider设置到ViewerterrainProvider属性中即可

# Cesium计算两点距离

# 直线距离

核心思想:两点坐标点向量做差求模长。

平面二维使用Cartesian2,空间三维使用Cartesian3,他们都有distance()方法能够计算两点之间的距离。 +但是他们两个类也都提供了distanceSquared()方法,比起distance()更加的高效(原因是关于资源开销问题:CPU擅长处理浮点数,但不适合平方根计算,因此单纯计算距离的时候会有更大的资源消耗,如果不需要精确的距离计算,使用距离的平方根也能达到相同的效果并且更加的高效)

# 垂直距离(两点之间的高程差)

核心思想:两个坐标点之间的高程之差。

如果没有高程未知,则通过计算出其高程,再进行求差。具体实现这是通过Cesium.sampleTerrainMostDetailed(terrainProvider, positions)方法得到带高程数据的坐标点

# 水平距离(两点之间的的水平距离差)

核心思想:相同高程的两点计算直线距离。

使两点的高程相同,再计算两点直线距离distance()/distanceSquared()即可

# 测地线(椭球体上的距离)

核心思想:按照椭球体计算曲线距离。

Cesium中存在一个测地线类EllipsoidGeodesic,实例化并通过setEndPoints设置起点和终点,通过surfaceDistance便可以获取到两点之间的地面距离

# 地形贴地距离(与地形有关)

核心思想:根据两点间的地形插值点,累加相邻两点之间的直线距离。

需要考虑两点之间的距离,如果大于过长(>=1km),适当降低插值精度;超过一定距离(>=100km)后,考虑使用测地线的方式进行计算两点距离

# Cesium与OpenLayer计算两点距离的区别(结果是否一致)

不完全一致。

OpenLayers提供了两种计算长度的方式:

  1. 基于投影平面->ol/geom/flat/length.lineStringLength,是通过平面的方式计算(两点距离公式)
  2. 基于椭球曲面->ol/sphere.getDistance/ol/sphere.getLength,通过两点/多点的地理坐标计算曲面距离

因此,在相同的椭球体下,同一个坐标点,使用相同的计算方式(基于投影平面/椭球曲面),两个框架计算两点距离是可以相等或近似相等;

# 如何理解Cesium中的position属性?如何实现漫游?

漫游,即在连续的时间段内,对指定的实体等物体进进行位置变换。

position基本是Entity/Primitive模块中的属性

参考文档: Property机制 (opens new window)

# Cesium常用坐标系(Degree/Radian/Cartesian)

Cesium中,常用的坐标主要有:

  • 屏幕坐标

    即屏幕的像素坐标,单位是像素,通过鼠标即可获得,或者可通过Cartesian2(x, y)实例化

  • 笛卡尔空间直角坐标系(世界坐标系)

    又称为世界坐标系,可通过Cartesian3(x, y, z)实例化获取。主要用来做空间位置变化(平移、旋转、缩放等),坐标原点在椭球体中心

  • 地理坐标系(弧度)

    Cesium中的地理坐标单位默认是弧度制,使用Gartographic(longtitude, latitude, height)实例化,当弧长与半径相等,则所形成的夹角便是1弧度

    弧度与角度的关系:

    • 弧度=π/180×角度
    • 角度=180/π×弧度
  • 经纬度坐标

    即测绘中的地理经纬度坐标系,默认是WGS84坐标,坐标原点在椭球质心。

    但是,Cesium没有具体的经纬度类,需要通过弧度进行转换:

    // 经纬度转弧度 
    +Cesium.Math.toRadians(degrees) 
    +// 弧度转经纬度
    +Cesium.Math.toDegrees(radians) 
    +

TODO:各坐标系的转换

参考文档: Cesium坐标系及坐标变换 (opens new window)

# Cesium怎么绘制点(Entity/Primitive)

Cesium中,有两种表达几何图形的方式,并且都能够实现图形的位置以及材质的设置:

  • Entity

    Entity实例是集成了多种形状的高层次对象(底层是通过Primitive的方式实现的),一个实例中可以包含点、线、面、体、模型、标签等等。这些形状都是需要***Graphics类对应实现。

  • Primitive

    Primitive是在场景中显示的几何体,每个Primitive实例中可以有一个或多个GeometryInstances几何体实例组成。GeometryGraphics类型类似,但比较不同的是,Geometry没有点这个类~~PointGeometry~~,而是直接实例化PointPrimitive

具体到添加点:

  1. 创建带PointGraphics点图形的Entities实例,添加至视图Viewer.entities中即可
  2. 创建PointPrimitive实例,添加至Scene.primitives中即可

# Cesium怎么加载一个模型(DataSource/Model)

# Cesium的Camera(俯仰角)

# Cesium和Three的坐标轴区别

# Cesium和Three的Camera区别(朝向)

# WebGL的渲染逻辑(顺序)

# Cesium如何加载倾斜摄影数据(GLTF GLB)

# 对ArcGIS三维模块的理解

+ + + diff --git a/dev_gis/special_3d_gis.html b/dev_gis/special_3d_gis.html new file mode 100644 index 0000000..630c622 --- /dev/null +++ b/dev_gis/special_3d_gis.html @@ -0,0 +1,36 @@ + + + + + + 三维GIS开发工程师 | kite-notes + + + + + + + + + +

# 三维GIS开发工程师

# OpenLayers如何加载ArcGIS地图服务

WebGIS中,客户端展示地图专题的主要方式是动态展示地图(根据范围等属性生成对应的地图图片)和瓦片影像(根据切片规则生成的瓦片数据)

OpenLayers根据以上两种方式提供了两种数据源ol/source/TileArcGISRest (opens new window)ol/source/ImageArcGISRest (opens new window)。除了基础的属性如urlprojection,还需要重点关注其加载函数tileLoadFunction/imageLoadFunction,其能过够定制化一些业务处理逻辑,也能够控制地图请求的状态,如ol/TileState

至于如何加载ArcGIS地图服务,只需要根据地图服务的类型,选择OpenLayers合适的数据源类(source),使用对应的图层类(layer)对其包裹,最终便可在地图(map)和视图(view)中显示。

# OpenLayers常用坐标系是什么?是否支持坐标系转换?

一般来说,互联网中地图通用的地理坐标系统是WGS84坐标系(ESPG:3857ESPG:4326)。因此OpenLayers也将该两个坐标系作为默认坐标系,但是OpenLayers提供了额外的坐标系定义类ol/proj/Projection (opens new window)。定义好后则可以支持已有坐标系的互转

# Cesium如何加载ArcGIS地图服务

OpenLayers的图层加载类似,需要一个图层实例(ImageryProvider)及其内部的数据源(Cesium.***ImageryProvider

对于ArcGIS地图服务来说,主要是:

  1. 通用WebMapServiceImageryProvider(加载WMS服务,除ArcGIS之外也支持其他厂商的地图服务加载)
  2. 通用WebMapTileServiceImageryProvider(加载WMTS服务,支持KVP和RESTful格式)
  3. Cesium提供的ArcGIS用数据源类ArcGisMapServerImageryProvider(加载WMTS服务)
  4. ArcGISTiledElevationTerrainProvider(加载地形服务)

最终,对于一般的地图服务(如WMS服务、WMTS服务),可以通过ImageryLayerCollection收集所有***ImageryProvider,并设置到ViewerimageryLayers属性中(其实也是Viewerscene属性的global属性的imageryLayers属性)。对于地形服务,则通过将ArcGISTiledElevationTerrainProvider设置到ViewerterrainProvider属性中即可

# Cesium计算两点距离

# 直线距离

核心思想:两点坐标点向量做差求模长。

平面二维使用Cartesian2,空间三维使用Cartesian3,他们都有distance()方法能够计算两点之间的距离。 +但是他们两个类也都提供了distanceSquared()方法,比起distance()更加的高效(原因是关于资源开销问题:CPU擅长处理浮点数,但不适合平方根计算,因此单纯计算距离的时候会有更大的资源消耗,如果不需要精确的距离计算,使用距离的平方根也能达到相同的效果并且更加的高效)

# 垂直距离(两点之间的高程差)

核心思想:两个坐标点之间的高程之差。

如果没有高程未知,则通过计算出其高程,再进行求差。具体实现这是通过Cesium.sampleTerrainMostDetailed(terrainProvider, positions)方法得到带高程数据的坐标点

# 水平距离(两点之间的的水平距离差)

核心思想:相同高程的两点计算直线距离。

使两点的高程相同,再计算两点直线距离distance()/distanceSquared()即可

# 测地线(椭球体上的距离)

核心思想:按照椭球体计算曲线距离。

Cesium中存在一个测地线类EllipsoidGeodesic,实例化并通过setEndPoints设置起点和终点,通过surfaceDistance便可以获取到两点之间的地面距离

# 地形贴地距离(与地形有关)

核心思想:根据两点间的地形插值点,累加相邻两点之间的直线距离。

需要考虑两点之间的距离,如果大于过长(>=1km),适当降低插值精度;超过一定距离(>=100km)后,考虑使用测地线的方式进行计算两点距离

# Cesium与OpenLayer计算两点距离的区别(结果是否一致)

不完全一致。

OpenLayers提供了两种计算长度的方式:

  1. 基于投影平面->ol/geom/flat/length.lineStringLength,是通过平面的方式计算(两点距离公式)
  2. 基于椭球曲面->ol/sphere.getDistance/ol/sphere.getLength,通过两点/多点的地理坐标计算曲面距离

因此,在相同的椭球体下,同一个坐标点,使用相同的计算方式(基于投影平面/椭球曲面),两个框架计算两点距离是可以相等或近似相等;

# 如何理解Cesium中的position属性?如何实现漫游?

漫游,即在连续的时间段内,对指定的实体等物体进进行位置变换。

position基本是Entity/Primitive模块中的属性

参考文档: Property机制 (opens new window)

# Cesium常用坐标系(类型)

Cesium中,常用的坐标主要有:

  • 屏幕坐标

    即屏幕的像素坐标,单位是像素,通过鼠标即可获得,或者可通过Cartesian2(x, y)实例化

  • 笛卡尔空间直角坐标系(世界坐标系)

    又称为世界坐标系,可通过Cartesian3(x, y, z)实例化获取。主要用来做空间位置变化(平移、旋转、缩放等),坐标原点在椭球体中心

  • 地理坐标系(弧度)

    Cesium中的地理坐标单位默认是弧度制,使用Gartographic(longtitude, latitude, height)实例化,当弧长与半径相等,则所形成的夹角便是1弧度

    弧度与角度的关系:

    • 弧度=π/180×角度
    • 角度=180/π×弧度
  • 经纬度坐标

    即测绘中的地理经纬度坐标系,默认是WGS84坐标,坐标原点在椭球质心。

    但是,Cesium没有具体的经纬度类,需要通过弧度进行转换:

    // 经纬度转弧度 
    +Cesium.Math.toRadians(degrees) 
    +// 弧度转经纬度
    +Cesium.Math.toDegrees(radians) 
    +

TODO:各坐标系的转换

参考文档: Cesium坐标系及坐标变换 (opens new window)

# Cesium怎么绘制点(Entity)

# Cesium怎么加载一个模型(Primitive)

# Cesium的Camera(俯仰角)

# Cesium和Three的坐标轴区别

# Cesium和Three的Camera区别(朝向)

# WebGL的渲染逻辑(顺序)

# Cesium如何加载倾斜摄影数据(GLTF GLB)

# 对ArcGIS三维模块的理解

+ + + diff --git a/dev_gis/tool_mapshaper.html b/dev_gis/tool_mapshaper.html new file mode 100644 index 0000000..04ecff5 --- /dev/null +++ b/dev_gis/tool_mapshaper.html @@ -0,0 +1,87 @@ + + + + + + 「小工具」mapshaper | kite-notes + + + + + + + + + +

# 「小工具」mapshaper

# 简介

mapshaper (opens new window)是一个用于编辑多种地理空间数据格式的地理处理工具,现支持ShapefileGeoJSONTopoJSONBDFCSV格式

# 主要功能

  1. 支持导入多种开源数据格式
  2. 支持基本的空间操作,如属性编辑、要素类型转换、裁剪、擦除、合并、概化(支持Douglas-PeuckerVisvalingam-Whyatt算法 (opens new window))等等
  3. 支持文件导出,实现数据格式转换
  4. 支持使用强大的命令行处理地理数据

# 如何使用

# 联网使用

进入mapshaper的官网 (opens new window)便是一个工具,直接上传文件后根据自身需求处理地理空间数据即可

# 本地使用

  • 全局安装mapshaper依赖包

    npm i -g mapshaper
    +
  • 打开图形化界面

    mapshaper-gui
    +

    执行该指令后,浏览器指定打开与mapshaper官网一样,但功能稍微不一样的页面(其核心功能不变)

  • 查看帮助文档

    # 所有指令的帮助列表
    +mapshaper -h
    +
    +# 具体指令的帮助文档(语法+例子)
    +mapshaper -h <command>
    +

# 指令的使用

# 文件操作

# 文件导入
+
+# 文件导出(文件格式转换)
+# name: 文件名称
+# ext: 文件扩展名 
+#      shp/json/geojson/topojson -> 输出空间信息+属性信息
+#      dbf/csv                   -> 输出属性信息
+#      svg                       -> 矢量图片
+mapshaper <file> -o <name>.<ext>
+

# 获取数据集信息

# 获取图层信息
+# target: 必填 图层名称列表(多图层用逗号分隔)
+mapshaper <file> -info <target>
+
+# 获取要素信息
+# expression: 必填,JS布尔表达式
+# target: 选填,图层名称列表(多图层用逗号分隔)
+mapshaper <file> -inspect <expression> [<target>]
+

# 坐标系转换

# projDef: 坐标系定义,使用Proj.4定义或者坐标系别名
+mapshaper <file> -proj <projDef>
+

# 数据概化(简化)

「算法」概化

# 一般概化(默认使用基于weight的Visvalingam-Whyatt算法)
+# percentage: 百分比,数值越小概化程度越高,如10%
+mapshaper -simplify <percentage>
+
+# Douglas-Peucker
+mapshaper <file> -simplify <percentage> dp
+# Visvalingam-Whyatt
+# 基于有效区域(effective area)
+mapshaper <file> -simplify <percentage> visvalingam
+# 基于权重区域(weighted area)
+mapshaper <file> -simplify <percentage> weighted
+

# 要素类型转换

# 点/面 -> 线
+mapshaper <file> -lines
+# 线 -> 面
+mapshaper <file> -polygon
+

# 空间操作

# 裁剪
+mapshaper <file1> -clip <file2> -o <file3>
+# 擦除
+mapshaper <file1> -erase <file2> -o <file3>
+# 融合
+# 同一个图层,所有要素进行融合
+mapshaper <file> -dissolve
+# 同一个图层,相邻的要素进行融合
+mapshaper <file> -dissolve2
+# ...
+

# 编辑属性表

# expression: 必填,JS布尔表达式
+mapshaper <file> -each <expression>
+

# 数理统计

# expression: 函数表达式,sum() average() median() max() min() count()
+# 支持链式指令执行,即多个-calc指令
+mapshaper <file> -calc <expression>
+

# 文档参考

「GIS工具」GISer的小军刀-mapshaper (opens new window)

「GIS笔记」Mapshaper命令行使用入门 (opens new window)

「GIS笔记」Mapshaper命令行通用格式说明 (opens new window)

+ + + diff --git a/env_deploy/index.html b/env_deploy/index.html new file mode 100644 index 0000000..8f32811 --- /dev/null +++ b/env_deploy/index.html @@ -0,0 +1,23 @@ + + + + + + 安装部署 | kite-notes + + + + + + + + + +
+ + + diff --git a/env_deploy/soft_db_kingbase.html b/env_deploy/soft_db_kingbase.html new file mode 100644 index 0000000..dedb664 --- /dev/null +++ b/env_deploy/soft_db_kingbase.html @@ -0,0 +1,53 @@ + + + + + + Kingbase(人大金仓数据库) | kite-notes + + + + + + + + + +

# Kingbase(人大金仓数据库)

# 安装

# 检查安装前的基础环境

执行kdb_check.sh脚本,检查安装前的系统环境,在安装前将所需工具/配置进行调整,用于后续执行人大金仓安装

bash kdb_check.sh
+

# 命令行交互安装

在安装人大金仓安装之前,修改kdb_install.sh脚本的自定义配置,也可以选择默认安装

vim kdb_install.sh
+

命令行交互安装-自定义配置

执行kdb_install.sh脚本,安装人大金仓安装主程序

bash kdb_install.sh
+

安装过程的选择:

  1. 版本选择:R6

    命令行交互安装-自定义配置

  2. 兼容模式:Orcale兼容

    命令行交互安装-自定义配置

  3. 大小写敏感:敏感

    命令行交互安装-自定义配置

安装完成后,会提供将来启动人大金仓服务的指令,并立即启动人大金仓服务

命令行交互安装-自定义配置

# 创建数据库

# 空间数据库

需要先创建空间数据库用户,再创建空间数据库、空间数据库引擎和插件拓展

ksql -U SYSTEM -W 5Y5#123 -d TEST
+
+CREATE DATABASE gisdata;
+create user gisdata with password 'gisdata#123';
+

配置kgis_tools.sh脚本

配置kgis_tools.sh脚本

执行脚本kgis_tools.sh

su kingbase
+
+cd ${SH_PATH}
+
+./kgis_tools.sh init
+./kgis_tools.sh create
+

执行kgis_tools.sh脚本

注:上图ERROR错误,根据人大金仓技术支持反馈,可能是当时这一步没有重新加载配置文件成功导致的,因此可以尝试单独执行该操作。

su kingbase
+
+ksql -U SYSTEM -W 5Y5#123 -d gisdata
+
+alter system set allow_system_table_dml = on;
+select sys_reload_conf();
+update pg_proc set proisstrict=false where proname like '%addgeo%' and proargtypes='1043 1043 1043 1043 23 1043 23 16';
+alter system set allow_system_table_dml = off;
+select sys_reload_conf();
+

# 参考文档

+ + + diff --git a/env_deploy/soft_gis_geoscene.html b/env_deploy/soft_gis_geoscene.html new file mode 100644 index 0000000..cc00a2f --- /dev/null +++ b/env_deploy/soft_gis_geoscene.html @@ -0,0 +1,27 @@ + + + + + + kite-notes + + + + + + + + + +
+ + + diff --git a/env_deploy/tool_build_jenkins.html b/env_deploy/tool_build_jenkins.html new file mode 100644 index 0000000..6c68b92 --- /dev/null +++ b/env_deploy/tool_build_jenkins.html @@ -0,0 +1,116 @@ + + + + + + Jenkins | kite-notes + + + + + + + + + +

# Jenkins

Jenkins是一个独立的开源软件项目,是基于Java开发的一种持续集成工具,用于监控持续重复的工作,旨在提供一个开放易用的软件平台,使软件的持续集成变成可能。 +前身是Hudson是一个可扩展的持续集成引擎。可用于自动化各种任务,如构建,测试和部署软件。 +Jenkins可以通过本机系统包Docker安装,甚至可以通过安装Java Runtime Environment的任何机器独立运行。1

# 安装+部署

# 安装

# 1. war包安装(Liunx)

  • 准备Jenkins安装包jenkins.war

  • 准备Jenkins启动/停止脚本(/)

    • 启动脚本jenkins-start.sh
    #!/bin/bash 
    +#Configs
    +WAR_NAME=jenkins.war
    +WAR_PATH=/opt/software/jenkins/
    +WAR_FILE=$WAR_PATH/$WAR_NAME
    +
    +echo "authorize .sh"
    +chmod 775 $WAR_FILE
    +
    +echo "open jenkins port 8020"
    +firewall-cmd --add-port=8020/tcp --permanent
    +firewall-cmd --reload
    +
    +nohup java -jar $WAR_PATH/jenkins.war --httpPort=8020 > $WAR_PATH/jenkins.log 2>&1 &
    +
  • 执行启动脚本jenkins-start.sh

# 2. Docker安装(Liunx)2

# 查找jenkins镜像
+docker search jenkins
+
+# 选择并拉取适合本机环境的jenkins镜像,以jenkins/jenkins:latest为例
+docker pull jenkins/jenkins:latest
+
+# 创建宿主挂在目录
+mkdir -p /opt/env/docker/jenkins_home
+chmod 777 /opt/env/docker/jenkins_home
+# 创建并运行容器实例
+# -p 10240:8080 ===> 端口映射,后续使用10240端口访问jenkins主页面
+# -p 10241:50000 ===> 端口映射
+# -v /opt/env/docker/jenkins_home:/var/jenkins_home ===> jenkins主目录挂载目录绑定
+# -v /etc/localtime:/etc/localtime ===> 容器使用和服务器同样的时间设置
+docker run -d 
+  --name jenkins \
+  -p 10240:8080 \
+  -p 10241:50000 \
+  -v /opt/env/docker/jenkins_home:/var/jenkins_home \
+  -v /etc/localtime:/etc/localtime \
+  jenkins/jenkins
+
+# 运行成功后,通过{IP}:{PORT}访问主界面
+# 例如:192.168.1.36:10240
+

# 部署

# 通过浏览器客户端对Jenkins进行可视化部署

  • 输入初始密码(初始密码可以从jenkins-start.sh脚本输出的log日志中查看,也可通过cat/vi/vim指令对下图红框文件使用进行查看)

部署-初始密码

  • 安装插件时,选择推荐插件进行安装

部署-推荐插件

  • 注册Jenkins管理员账户

  • 集成插件安装(安装完成后,需要重启Jenkins。也可以在安装插件过程中,勾选自动重启

    • NodeJS Plugin
    • Subversion Plug-in
    • Maven Integration plugin
    • Publish Over SSH

# 全局配置(配置构建环境)

构建集成环境可以使用本地环境,也可以使用Jenkins自主选择安装环境

  • Maven配置(本地环境;注意,有两处需要配置)

Maven配置1

Maven配置2

  • JDK配置(本地环境)

JDK配置

  • NodeJS配置(本地环境;该配置项需要安装完NodeJS Plugin插件才会出现)

NodeJS配置

  • 凭证配置(分SVNGit配置) +
    • 通用步骤(找到账号凭证配置)

      账号凭证项 全局凭证

    • SVN

      账号凭证配置

    • Git

      账号凭证配置

# 项目构建

在Jenkins中,存在视图和项目两个重要的概念。项目是一个个独立的构建项,而视图可以存放着许多构建项,即项目的容器。每个构建项中有许多配置项,如源码管理构建触发器构建环境构建预处理构建后处理等等操作

# 视图构建

"构建视图" "构建视图"

# 项目构建-通用操作

  • 源码管理。填入源码地址+凭证
  • 在【构建触发器】标签页中勾选触发远程构建Poll SCMBuild after orther projects are built选项是构建情况而定(构建后端资源需要,构建前端资源不需要) +
    • 触发远程构建:可通过<JENKINS_URL>/job/<ITEM_NAME>/build?token=<TOKEN>的方式进行远程构建,不需要进入Jenkins管理界面

    • Poll SCM:计划构建,用于定时检查源码变更并构建

      # 该语句会输出上次一的构建时间以及下一次的将要构建的时间    
      +H 1 * * *
      +

# 后端项目构建

  • 设置完通用操作后,在【Build】标签页中,设置Goals and options配置项

    • clean install:即先清理原有的再构建新的
    • clean package -DskipTests:即先清理原有的再打包,同时不执行测试用例
  • 注意构建代码前后处理

    • 构建代码前处理:主要是判断该JAR包的端口是否存在,存在则杀死->Shell脚本

    • 构建代码后处理:移动JAR包到指定目录,重启启动

      #!/bin/bash
      +# 构建名称
      +ITEM_NAME=my-jar
      +# 目标存放目录
      +TARGET_PATH=/home/jar
      +
      +# 复制JAR包到指定目录下,并统一名称
      +cp /root/.jenkins/workspace/$ITEM_NAME/target/$ITEM_NAME-0.0.1-SNAPSHOT.jar $TARGET_PATH/$ITEM_NAME.jar
      +# 启动JAR包,打印输出日志文件
      +echo "start $ITEM_NAME"
      +nohup java -jar $TARGET_PATH/$ITEM_NAME.jar > $TARGET_PATH/out/$ITEM_NAME.out 2>&1 &
      +

# 前端项目构建

  • 设置完通用操作后,1. 在【构建环境】勾选Provide Node & npm bin/ folder to PATH ,即使用先前在jenkins中配置好的node环境
  • 在【构建】标签页中,添加执行Shell脚本 +
    • 构建代码后处理:移动构建后的文件夹到指定目录(一般是应用服务器[如Tomcat]的目录,具体由应用服务器的配置决定)

      #!/bin/bash
      +# 构建名称
      +ITEM_NAME=my-frontend
      +# 前端工程名称
      +PROJRCT_NAME=my-nest
      +# 前端工程后名称
      +PROJECT_ALIAS=nest
      +# 静态目录
      +STATIC_PATH=/home/nest
      +# npm构建脚本
      +BUILD_SCRIPT=build:$PROJECT_ALIAS
      +#DATE=$(date +%Y%m%d%H%M%S)
      +
      +cd /root/.jenkins/workspace/$ITEM_NAME/$PROJRCT_NAME
      +
      +#TODO: 时间备份
      +#mv $STATIC_PATH/$PROJECT_ALIAS $STATIC_PATH/$PROJECT_ALIAS/$DATE
      +
      +# 依赖安装+构建
      +npm install
      +npm run $BUILD_SCRIPT
      +
      +if [ $? -ne 0 ]; then
      +  exit 0
      +else
      +  rm -rf $STATIC_PATH/$PROJECT_ALIAS
      +    #cp -r /root/.jenkins/workspace/$ITEM_NAME/$PROJRCT_NAME/$PROJECT_ALIAS $STATIC_PATH
      +    find ./$PROJECT_ALIAS | grep -vE "/.svn|/.git" | cpio -pdm $STATIC_PATH
      +fi
      +

# 构建后处理(可选)3

构建后处理比较常用的操作是文件传输+文件路径的改变+程序启动,需要用到先前安装的插件Publish Over SSH

# 配置远程连接

前往【系统配置】,找到【Publish over SSH】配置项的【SSH Servers】小项

  • 配置连接信息,保存即可

    配置连接信息

  • 在构建项目中配置【构建后操作】操作

    • Source files:需要传输的文件/文件夹
    • Remove prefix:需要移除的目录前缀,基于Source files路径
    • Remote directory:远程的目录(默认为远程用户的目录,root -> /root)
    • Exec command:需要执行的操作

    构建后操作

# 参考文档

  1. Jenkins中文文档-W3C School (opens new window)
  2. Docker安装Jenkins详细教程 (opens new window)
  3. 基于Docker安装Jenkins,并配置使用Jenkins打包Node前后端服务部署到远程服务器 (opens new window)
+ + + diff --git a/env_deploy/tool_cvs_git.html b/env_deploy/tool_cvs_git.html new file mode 100644 index 0000000..129452e --- /dev/null +++ b/env_deploy/tool_cvs_git.html @@ -0,0 +1,339 @@ + + + + + + kite-notes + + + + + + + + + +

# Git

Git is a free and open source distributed version control system designed +to handle everything from small to very large projects with speed and efficiency. +—— Git是一个免费的开源分布式版本控制系统,可以快速高效地处理从小到大的所有项目。

GitLinus Torvalds (opens new window)为了帮助管理Linux内核开发而开发的一个开放源码的版本控制软件

# Git vs. SVN

Git vs SVN

# 联系与区别

  1. 核心架构不同最核心的区别):Git分布式的版本控制系统,而SVN集中式的,因此,Git支持离线工作,SVN必须联网才能工作
  2. 概念和指令不同SVN概念和指令较少,上手容易,而Git概念多且复杂,如addcommitpushfetchpull等等,概念多但也意味着功能更加强大
  3. 分支管理不同Git可以有本地分支,且分支的指针指向的某次提交,而SVN没有本地分支,它的分支只是一个拷贝的目录。 +因此,Git分支创建和切换十分便捷,并且在开发过程中遇到突发事情需要另外处理时,使用Gitstash将当前改动临时存储,使得分支管理更加灵活
Git SVN
服务器架构 在本地安装并充当服务器和客户端 需要中央服务器和用户客户端
修订 Git 是一个 SCM(源代码管理)工具。因此,它没有全局修订号 SVN 是一个版本控制系统。因此,它具有全局修订号
存储库克隆 支持 不支持
存储格式 元数据 文件
存储要求 处理大型二进制文件的能力有限 除了代码之外,还可以处理大型二进制文件
分支 分支是对某个提交的引用。可以随时创建、删除和更改它们,而不会影响其他提交。 分支被创建为存储库内的目录,当分支准备好时,它被提交回主干
访问控制和权限 允许所有贡献者对整个代码库具有相同的权限 允许对每个文件级别和每个目录级别进行读写访问控制的细化权限
上手容易度 困难 简单
加密散列 为了防止存储库损坏(由于网络问题或磁盘故障),Git 对内容进行哈希加密。 不适用
许可证 GNU(通用公共许可证) 在 Apache 许可下开源
变更追踪 存储库级别 文件级别
原开发者 Linus Torvalds(为 Linux 内核代码控制而开发) CollabNet公司

# 安装与配置

# 安装

前往Git (opens new window)官网下载安装包,默认安装即可

# 配置(SSH)

  • 修改本地配置config

    # 设置全局用户名称
    +git config --global user.name <username>
    +# 设置全局用户邮箱
    +git config --global user.email <email>
    +
  • 打开Git Bash,生成rsa文件,以及ssh

    # 生成新的ssh
    +# <email>: 电子邮箱
    +#-t: 密钥类型, 可以选择 dsa | ecdsa | ed25519 | rsa;
    +#-b: 指定密钥长度
    +#-f: 密钥目录位置, 默认为当前用户home路径下的.ssh隐藏目录, 也就是~/.ssh/, 同时默认密钥文件名以id_rsa开头. 如果是root用户, 则在/root/.ssh/id_rsa, 若为其他用户, 则在/home/<username>/.ssh/id_rsa;
    +#-C: 指定此密钥的备注信息, 需要配置多个免密登录时, 建议携带;
    +ssh-keygen -t rsa -b 4096 -C "<email>"
    +
    +# 按回车三次
    +# 查看生成的文件,并复制至Github上
    +cat ~/.ssh/id_rsa.pub
    +
  • 在Github上创建ssh key

  • 检查是否能够通过SSH与GitHub通信

    • 如果出现Hi xxx! You've successfully authenticated, but GitHub does not provide shell access.,说明配置成功;
    • 如果出现Permission denied (publickey).,说明配置失败,需要重新操作。
    # -T: 禁止分配伪终端
    +ssh -T git@github.com
    +# 若有提示则输入yes
    +

# 基本使用

# 基本概念

Git工作流

  • Workspace:工作区,也称工作副本,就是计算机上的一个目录。开发者日常主要的开发工作都在这完成 +
    • 基于开发分支develop创建的特性分支feature/xxx,进行功能模块开发\
    • 基于开发分支develop创建的版本分支release/x.x.x,进行版本的发布说明
    • 基于主分支main的热修复分支hotfix/xxx,对上线的产品进行快速修复
    • 等等...
  • Respository:本地版本库,也称为本地仓库。在这既可以与工作空间的状态进行管理(主要是对分支的管理操作):切换本地分支、本地版本库与远程版本库的改动推送/拉取
  • Remote: 远程版本库,也称为远程仓库。用于存储各种正式代码分支,与本地版本库进行相关操作 +
    • 主分支main
    • 开发分支develop
    • 等等...
  • Index:暂存区,类似缓存的地方,临时保存修改内容:比如新增改动、提交改动、暂存/恢复先前修改。每次操作后生成的索引值(基于SHA-1算法生成的哈希校验和),一般只需要确认其前3~4位就能够找到对应的改动记录。

# 工作区(Workspace)管理

# 文件状态

在Git中,文件状态分为已跟踪未跟踪,除了已跟踪的文件以外,其他都是未跟踪文件。 +已跟踪的文件是指那些被纳入了版本控制的文件,经过一段时间的工作后,状态可能是如下四种:

  • Untracked(未跟踪):未被Git跟踪的文件,一般为新建/删除文件
  • Unmodified(未改动):已被Git跟踪的文件,但在工作过程中未被修改的文件
  • Modified(有改动):已被Git跟踪的文件,并且在工作中发生改动的文件
  • Staged(已暂存):已被Git跟踪的文件,并且已被添加至暂存区

文件的状态变化周期

# 常用指令

  • 查看状态

    git status查看当前工作区的文件状态,如当前处在的分支、改动的文件、未跟踪的文件等...

    # -s: 状态简览
    +git status [--short|-s]
    +
  • 跟踪新增的文件/暂存已修改的文件

    git add不仅可以跟踪新增文件,还能够将已修改的文件进行暂存, +每次add都将文件添加至暂存区,并且生成一个索引值,该索引值标识此次提交的工作树(working tree)的快照,快照的内容用于后续暂存的提交。

    # pathspec: 具体暂存文件的路径
    +git add [file1] [file2] ...
    +# 将所有改动的文件添加至暂存区,不管是否原本已经存在提交索引
    +git add -A
    +# 将当前目录下的所有文件添加至暂存区
    +git add .
    +# 强制新增改动,一般用于新增.gitignore文件的改动
    +git add -f
    +
  • 查看已暂存和未暂存的修改

    git diff可以将当前工作副本与暂存区的工作树进行对比,发现改动的文件以及改动的内容;也可以查看已暂存的将要添加到下次提交的改动内容

    # 查看当前工作区与最近一次暂存内容的改动区别
    +git diff
    +# 查看已暂存的将要添加到下次提交里的内容的改动区别
    +git diff [--cached|--staged]
    +
  • 提交暂存的修改

    将暂存区的改动内容提交至本地仓库,在此之前需要确认是否还有改动遗漏,有则需要再git add添加改动,否则接下来的提交不会记录尚未暂存的改动。 +因此,可以先git status查看当前工作区状态,确保都暂存再执行git commit

    # 会自动启动编辑器来输入提交信息
    +git commit
    +# -m:提交信息
    +git commit -m "<message>"
    +# -a: 跳过git add过程,直接跟踪的文件暂存起来并提交
    +git commit -a -m "<message>"
    +
  • 移除文件

    git rm能够将文件从暂存区工作区中移除文件,这是彻底的移除文件。 +如果只是简单的从工作区删除文件,在git status中能看到删除的文件的改动状态则会变成deleted,然后再使用git rm将该文件改动添加至暂存区

    # 将工作区和暂存区的指定文件移除
    +git rm [file]
    +# 将暂存区的指定文件移除,但保留工作区中的对应文件
    +git rm --cached [file]
    +
  • 移动文件/文件更名

    在Git中,移动文件可以使用git mv完成,正如Linux的mv一样,能够移动文件,也能够更改文件名。 +若是更改文件名称,在git status中能看到更名的文件的改动状态则会变成renamed。 +本质上,使用git mv更名也是一次文件的删除rm再添加add

    git mv file_from file_to
    +

# 版本库(Repository)管理

# 本地版本库(Local)管理

  • 获取Git仓库
# 将当前文件夹初始化为Git仓库
+git init
+# 将远程仓库克隆至本地
+# url:协议地址(HTTPS|SSH)
+# dirname: 新目录名称
+git clone <url> [<dirname>]
+
  • 查看提交历史

    git log会根据时间顺序列出所有的提交,最近的一次提交列在最上面, +并且列出每个提交的 SHA-1 校验和作者的名字和电子邮件地址提交时间以及提交说明

# -p: 列出每次的修改内容
+# --stat:列出每次文件修改统计信息
+# --graph:使用ASCII字符列出分支、合并历史
+# --pretty: 美化日志格式,format=oneline | short | full | fuller,还支持format自定义格式化
+# -n:列出最近几次的提交日志
+# --since, --after: 时间过滤,从什么时候开始--since='2022-11-22'
+# --until, --before: 时间过滤,在什么时候之前--since='2022-11-22'
+# --author:作者过滤
+# ...
+git log [-p|--patch] [--stat] [--graph] [--pretty=<format>] [-<n>] [--since= | --after=] [--until= | --before=] [--author=]
+
+# 一行输出日志信息
+git log --pretty=oneline
+
+# 自定义格式化输出日志:"哈希值 - 作者名称, 据当下多长时间 : 提交说明"
+git log --pretty=format:"%h - %an, %ar : %s"
+# 自定义格式化+分支、合并情况的日志
+git log --pretty=format:"%h %s" --graph
+
  • 创建/切换分支

    创建本地分支可用git branch, +切换本地分支用的HEAD指向可用git switchgit checkout, +git checkout不仅能用于创建分支,还可以切换分支。

    # 创建【本地】分支
    +git branch <local>
    +# 切换【本地】分支,即将HEAD指针指向该分支
    +git switch <local>
    +git checkout <local>
    +# 创建并切换【本地】分支,并将HEAD指针指向该分支
    +git checkout -b <local>
    +
  • 合并分支

    Git的合并有两种方式:mergerebase。它们各有特点,根据不同场景选择使用能够实现较为理想的效果

    • merge

      当想将检出的分支合并至某一分支中(如main),则可以先切换至该分支main,然后合并检出的分支。

      可能会出现快速前进(fast-forward),即当两个分支需要合并时,如果一个分支能够顺着移动到另一个分支,则Git在合并时,只会简单的将指针向前推进; +合并时也可能会出现冲突,因此需要解决完后,通过git add将文件暂存,确定冲突已解决,再git commit提交此次合并

      git checkout <breach>
      +git merge <target>
      +# 可视化合并工具
      +git mergetool
      +
    • rebase

      基变(rebase)是将一个主题分支的修改通过“备份”,依序合并至目标基底分支上,并且丢弃掉主题分支上的所有提交记录,使得分支的提交记录更加地“线性”,更加清晰。

      但是需要注意的是,如果提交存在于本地仓库之外,而其他人可能基于这些提交进行开发,那么不要执行变基

      # 将当前分支合并至<basebranch>,如果传入<topicbranch>,则会合并将HEAD指向<topicbranch>
      +# -i:交互模式,能够修改版本提交的顺序。
      +# basebranch:目标基底分支
      +# topicbranch:主题分支
      +git rebase [-i|--interactive] <basebranch> [<topicbranch>]
      +
  • 拉取

    主要有两种方式:fetchpull

    1. fetch:拉取远程仓库代码到新分支,不合并当前分支的改动,需要手动merge,因此fetch后常与merge配合使用
    2. pull:拉去远程代码到本地,并自动合并当前改动
    # fetch + merge
    +git fetch [origin <remote>[:<local>]] [--all]
    +git merge <remote>
    +
    +# pull
    +# --rebase:拉取并基变远程仓库到本地,防止他人将基变推送至远程仓库导致记录缺失
    +git pull [--rebase] [origin <remote>:<local>] 
    +
  • 推送

    # 推送提交代码至远程仓库
    +git push
    +
  • 删除分支

    删除分支主要使用branch和参数-d/-D控制

    1. -d:常规删除
    2. -D:强制删除,相当于--delete --force
    # 删除【本地】分支
    +# 常规删除
    +git branch -d <local>
    +# 强制删除
    +git branch -D <local>
    +

# 远程版本库(Remote)管理

与本地仓库类似,远程仓库也存在分支、标签等,其分支以<remote>/<branch>的形式命名,remote的名称一般为origin,在检出远程分支时也能够重命名。

  • 创建分支

    # 创建并切换分支
    +git push <remote> <localbranch>:<remotebranch>
    +
  • 删除分支

    # 删除【远程】分支
    +# 常规删除
    +git push <remote> [-d|--delete] <localbranch>
    +# 强制删除
    +git push <remote> -D <localbranch>
    +# 推送空分支
    +git push <remote> :<localbranch>
    +
  • 跟踪分支

    # 当存在本地分支,想远程创建同名分支+跟踪
    +git push <remote> [-u|--set-upstream] <local>
    +# 当远程存在分支,想本地创建同名分支+跟踪
    +# track:跟踪分支
    +# alias:分支重命名,默认与远程分支相同
    +git checkout -b [--track] [alias] <remote>/<remotebranch>
    +

# 暂存区(Index)管理

  • 撤销操作
    • 撤销提交,当提交信息填写错误或者漏掉几个文件没有添加至暂存区,因此需要撤销原本的提交,运行带上--amend参数的提交命令即可。 +如果自上次提交以来没有做任何修改而执行带--amend参数提交指令,Git会保持原来的快照,只修改提交信息; +如果做了修改,则需要将改动的文件add后,再执行带--amend参数提交指令,这次提交会启动文本编辑器,并显示第一次提交信息, +在此基础上修改后作为第二次提交信息,第二次提交会代替第一次提交的结果。

      git commit --amend
      +
    • 对已在暂存区的文件撤销,例如添加两个文件修改至暂存库,需要撤销其中一个文件的改动,则可以使用git resetgit restore

    • 撤销工作区的文件修改,恢复到上一次提交时的样子,使用git resetgit restore也可以实现

      git reset HEAD [file1]...
      +git restore [file1]...
      +

# 进阶使用

# Git Hook

钩子(Hook)一般是在执行特定动作时触发一些自定义脚本,Git中的钩子存放在.git/hooks目录下,当初始化Git仓库后,会默认存放后缀为.sample的钩子示例。 +若需要开启,只需要移除这个后缀即可。

Git中存在两大类钩子:客户端钩子服务端钩子。客户端钩子主要用于提交合并前后的操作。服务端钩子主要用于接收被推送的提交的联网操作。

  • 客户端钩子 +
    • 提交工作流钩子 +
      • pre-commit:在输入提交信息前运行。它用于检查即将提交的快照,常用于查找受否存在遗漏,测试运行是否正常,代码编写是否规范等等...
      • prepare-commit-msg:在启动提交信息编辑器之前,默认信息被创建之后运行。常与提交信息模板搭配使用,动态插入信息
      • commit-msg:在提交信息时的运行。如果以钩子脚本非零值退出,Git将放弃提交。常用于在提交通过前验证项目状态或提交信息
      • post-commit:在整个提交过程完成后运行。一般用于通知之类的事情
    • 电子邮件工作流钩子 +
      • applypatch-msg
      • applypatch-msg
      • post-applypatch
    • 其它客户端钩子 +
      • pre-rebase
      • post-rewrite
      • post-checkout
      • post-merge
      • pre-push
  • 服务端钩子 +
    • pre-receive
    • update
    • post-receive

# 团队协作流程

Git团队协作开发流

目前主流的Git团队协作开发主要用主分支master|main和开发分支develop来记录开发历史,而开发者的所有开发活动都基于开发分支上进行。

  • master:主分支,也可以命名为mainmain的命名是因为BLM运动而出现),这是仓库最主要、最稳定的代码版本,一般只有管理员有写入权限,用于保存发布版本历史,顺便打标签。
  • develop:开发分支,一般各种开发活动最终需要集成到该分支。后续考虑代码版本发布时,会基于该分支检出一个发布分支并进行版本发布
  • feature:功能开发分支,命名一般为feature/xxx。基于develop分支检出(相当于父分支为develop),开发完成后需要合并至develop,一般会出现冲突,需要处理完冲突再进行合并。
  • hotfix:紧急修复分支,命名一般为hotfix/xxx,唯一可以基于master分支检出的分支,修复完后需要合并回masterdevelop分支,并且在master打好标签。
  • release:发布分支,用于向外发布指定版本。

# 传统协作流

  • 新的功能(feature)

    每个新功能应该有独立的分支进行开发,这样能够在不干扰开发分支develop的前提下进行本地开发,开发完成后再合并回开发分支即可

    # 一般来说,远程仓库会优先创建好develop分支,用于日常开发。
    +# 开发者只需要基于develop分支创建feature分支进行开发,可选择性地在远程中创建跟踪分支
    +git checkout -b feature/xxx develop
    +git push -u origin feature/xxx
    +
    +# 开发完成后,需要合并至develop分支(可能会出现冲突,出现则需要解决)
    +# 1. 先在本地仓库提交修改
    +git add -A
    +git commit -m "feat:xxx"
    +
    +# 2. 更新远程develop分支
    +git pull origin develop
    +
    +# 3. 合并feat分支至本地develop分支(可能需要处理冲突)
    +git checkout develop
    +git merge --no-ff feature/xxx
    +
    +# 4. 推送至远程develop分支
    +git push origin develop
    +
    +# 5. 删除本地和远程分支
    +git branch -d feature/xxx
    +git push origin -d feature/xxx
    +
  • 新的发布版本(release)

    发布前的准备,包括一些清理工作、全面的测试、文档的更新以及任何其他的准备工作

    # 基于develop分支检出一个新分支用于版本发布
    +git checkout -b <VERSION> develop
    +
    +# 发布前的工作完成后,需要将分支合并至main和develop中,最后删除本地的发布分支
    +git checkout main
    +git merge <VERSION>
    +git push
    +
    +git checkout develop
    +git merge <VERSION>
    +git push
    +
    +git branch -d <VERSION>
    +
    +# 当合并至主分支main中,需要打上合适的标签
    +git tag -a <VERSION> -m "xxx" main
    +git push --tags
    +
  • 新的修复补丁(hotfix)

    当主分支出现漏洞,需要从该分支中检出修复分支,将漏洞修复完成后再合并至主分支,同时也要合并至开发分支

    git checkout -b hotfix/xxx master
    +
    +git checkout master
    +git merge hotfix/xxx
    +git push
    +
    +git checkout develop
    +git merge hotfix/xxx
    +git push
    +git branch -d hotfix/xxx
    +

# 高效协作流:Git Flow

在Git中,简单地封装了一个指令git flow,用于创建标准的工作流,如果熟悉Git的工作流,可以完全不需要这个指令。 +这个指令可以让我们更方便地进行工作流管理

git flow工具

  • 初始化Git Flow工作流

    初始化Git工作流,主要是配置master、develop、feature、relase、hotfix等分支

    git flow init [-d | -f]
    +
  • 新的功能(feature)

    # 开始新Feature的开发工作 
    +git flow feature start <NAME>
    +# 发布Feature分支,相当于push至远程开发分支
    +git flow feature publish <NAME>
    +# 从远程仓库获取发布的Feature
    +git flow feature pull origin <NAME>
    +# 完成并关闭Feature分支
    +git flow feature finish <NAME>
    +
  • 新的发布版本(release)

    # 开始一个Release分支
    +git flow release start <VERSION> [BASE]
    +# 发布一个Release
    +git flow release publish <VERSION>
    +# 结束Release
    +git flow release finish <VERSION>
    +# 给主分支打标签
    +git tag -a <VERSION> -m "xxx" main
    +git push --tags
    +
  • 新的修复补丁(hotfix)

    # 开始一个Hotfix
    +git flow hotfix start <VERSION> [BASENAME]
    +# 结束一个Hotfix
    +git flow hotfix finish <VERSION>
    +

# 代码提交规范

# 主流的规范

<type>(<scope>): <subject>
+
+<body>
+
+<footer>
+

使用主流的Angular代码提交规范(如上代码块),主要分为三个部分:

  1. Header(标题行):必填,描述主要修改类型内容

    • type:commit类型

      feat: 新功能、新特性
      +fix: 修改bug
      +perf: 更改代码,性能优化
      +refactor: 代码重构(重构,在不影响代码内部行为、功能下的代码修改)
      +docs: 文档修改
      +style: 代码格式修改, 注意不是 css 修改(例如分号修改)
      +test: 测试用例新增、修改
      +build: 影响项目构建或依赖项修改
      +revert: 恢复上一次提交
      +ci: 持续集成相关文件修改
      +chore: 其他修改(不在上述类型中的修改)
      +release: 发布新版本
      +workflow: 工作流相关文件修改
      +
    • scope:说明commit影响的范围

      说明commit影响的范围,如global, common, route, component, utils, build...

    • subject:commit的简要说明

      简要说明commit的内容

  2. Body(主题内容):详细描述做了什么样的修改,为什么修改,以及开发的思路...

  3. Footer(页脚注释):可以写注释,引用Issues...

# 提交信息检测配置(husky+commmitizen+commitlint)

工具:

  • husky:主流Git Hook工具,Vue工程集成的是yorkie
  • commitizen:Git Commit Message规范工具
  • cz-conventional-changelog:传统日志
  • cz-customizable:自定义提交日志,需要配置
  • @commitlint/config-conventional:检测Git提交
  • @commitlint/cli:检测Git提交脚手架

# 前置安装

# git hook工具
+npm i husky -D
+npx husky-init
+

# 预提交配置

  1. 自动生成提交内容

    安装相关工具

    # 规范 commit message 的工具
    +npm i -g commitizen
    +# 使用传统commit规范提示
    +npx commitizen init cz-conventional-changelog --save-dev
    +# 传统commit规范package.json配置
    +"config": {
    +  "commitizen": {
    +    "path": "./node_modules/cz-conventional-changelog"
    +  }
    +}
    +
    +# (可选)使用自定义的commit规范提示,同时需要在根目录下新建.cz-config.js文件
    +npm i cz-customizable --save-dev
    +# 传统commit规范package.json配置
    +"config": {
    +  "commitizen": {
    +    "path": "./node_modules/cz-customizable"
    +  }
    +}
    +
  2. 配置自定义提交.cz-config.js文件

    module.exports = {
    +  // 可选类型
    +  types: [
    +    { value: "feat", name: "feat:     新功能" },
    +    { value: "fix", name: "fix:      修复" },
    +    { value: "docs", name: "docs:     文档变更" },
    +    { value: "style", name: "style:    代码格式(不影响代码运行的变动)" },
    +    {
    +      value: "refactor",
    +      name: "refactor: 重构(既不是增加feature,也不是修复bug)",
    +    },
    +    { value: "perf", name: "perf:     性能优化" },
    +    { value: "test", name: "test:     增加测试" },
    +    { value: "chore", name: "chore:    构建过程或辅助工具的变动" },
    +    { value: "revert", name: "revert:   回退" },
    +    { value: "build", name: "build:    打包" },
    +  ],
    +  // 消息步骤
    +  messages: {
    +    type: "请选择提交类型:",
    +    customScope: "请输入修改范围(可选):",
    +    subject: "请简要描述提交(必填):",
    +    body: "请输入详细描述(可选):",
    +    footer: "请输入要关闭的issue(可选):",
    +    confirmCommit: "确认使用以上信息提交?(y/n/e/h)",
    +  },
    +  // 跳过问题
    +  skipQuestions: ["body", "footer"],
    +  subjectLimit: 72, // subject文字长度默认是72
    +};
    +
  3. 指令替换

    配置完成后,提交信息则使用git cz替代git commit -m

# 提交信息检测

  1. 安装相关工具

    # 检测 commit message 的工具
    +npm i @commitlint/config-conventional @commitlint/cli -D
    +# 在根目录下新建创建commitlint.config.js文件+添加配置
    +"config": {
    +  "commitizen": {
    +    "path": "./node_modules/cz-conventional-changelog"
    +  }
    +}
    +# 创建commit-msg钩子
    +npx husky add .husky/commit-msg
    +# .husky/commit-msg文件添加
    +npx --no-install commitlint --edit $1
    +
  2. 配置commitlint.config.js文件

    module.exports = {
    +  extends: ["@commitlint/config-conventional"],
    +  rules: {
    +    "type-enum": [2, "always", ["upd", "feat", "fix", "refactor", "docs", "chore", "style", "revert"]],
    +    "type-case": [0],
    +    "type-empty": [0],
    +    "scope-empty": [0],
    +    "scope-case": [0],
    +    "subject-full-stop": [0, "never"],
    +    "subject-case": [0, "never"],
    +    "header-max-length": [0, "always", 72],
    +  },
    +};
    +

# 工具

# 学习/练手资源

Learn Git Branching (opens new window)

# 参考文档

  1. git flow的使用 (opens new window)
  2. 对比Git与SVN,这篇讲的很易懂 (opens new window)
  3. SVN vs. Git: 2021年哪个适合你 (opens new window)
  4. Pro Git (opens new window)
+ + + diff --git a/env_deploy/tool_hub_gitlab.html b/env_deploy/tool_hub_gitlab.html new file mode 100644 index 0000000..abaf0e3 --- /dev/null +++ b/env_deploy/tool_hub_gitlab.html @@ -0,0 +1,88 @@ + + + + + + GitLab | kite-notes + + + + + + + + + +

# GitLab

# 安装部署

# 以Docker Engine的方式安装

  • 拉取gitlab-ee镜像
docker pull gitlab/gitlab-ee:lastest
+
  • 运行容器
# 重点关注以下参数 --hostname -p
+docker run -d \
+  --hostname 192.168.1.36 \
+  -p 443:443 \
+  -p 8021:80 \
+  -p 8022:22 \
+  --name gitlab-ee \
+  --restart always \
+  -v /opt/env/docker/gitlab-ee/config:/etc/gitlab \
+  -v /opt/env/docker/gitlab-ee/logs:/var/log/gitlab \
+  -v /opt/env/docker/gitlab-ee/data:/var/opt/gitlab \
+  --shm-size 256m \
+  --privileged=true \
+  gitlab/gitlab-ee
+
  • 配置gitlab
vi /etc/gitlab/gitlab.rb
+
+external_url 'http://192.168.1.36'
+gitlab_rails['gitlab_ssh_host'] = '192.168.1.36'
+gitlab_rails['gitlab_shell_ssh_port'] = 8022
+
+# 如果内存不足时,则puma关闭,否则浏览器访问会出现502错误
+puma['enable'] = false
+
vi /var/opt/gitlab/gitlab-rails/etc/gitlab.yml
+
+# 修改http的端口
+production: &base
+  gitlab:
+    port: 8021
+

# GitLab使用

# 服务端常用指令

gitlab-ctl start # 启动所有 gitlab 组件
+gitlab-ctl stop # 停止所有 gitlab 组件
+gitlab-ctl restart # 重启所有 gitlab 组件
+gitlab-ctl status # 查看服务状态
+gitlab-ctl reconfigure # 启动服务
+vim /etc/gitlab/gitlab.rb # 修改默认的配置文件
+gitlab-rake gitlab:check SANITIZE=true --trace # 检查gitlab
+gitlab-ctl tail # 查看日志
+

# 用户/群组/项目管理

  1. 新增用户可以通过超级管理员用户root进入Admin Area进行新增用户/群组/项目

  2. 用户密码更改2

    • 可以通过UI界面进行更改;

    • 也可以通过服务端进行更改

      # 进入Rails console
      +gitlab-rails console
      +
      +# 三种方式查找用户
      +# 1. 通过用户名查找用户
      +user = User.find_by_username 'exampleuser'
      +# 2. 通过用户ID查找用户
      +user = User.find(123)
      +# 3. 通过电子邮箱查找用户
      +user = User.find_by(email: 'user@example.com')
      +
      +# 重置密码
      +new_password = 'examplepassword'
      +user.password = new_password
      +user.password_confirmation = new_password
      +
      +# 保存用户信息
      +user.save!
      +
      +exit
      +

      重置密码

# 用户配置(SSH配置)

参考Github配置SSH Key

# GitLab团队合作2

# 参考文档

  1. 重置密码 (opens new window)
  2. Git+GitLab团队协作 (opens new window)
+ + + diff --git a/env_deploy/tool_virtualize_docker.html b/env_deploy/tool_virtualize_docker.html new file mode 100644 index 0000000..f1c4973 --- /dev/null +++ b/env_deploy/tool_virtualize_docker.html @@ -0,0 +1,97 @@ + + + + + + Docker | kite-notes + + + + + + + + + +

# Docker

# 安装

# 1. 源码安装

TODO...

# 2. yum安装1

# 更新yum
+yum update
+# 安装工具包
+yum install -y yum-utils
+
+# 建立Docker仓库 (映射仓库地址)
+yum-config-manager \
+    --add-repo \
+    https://download.docker.com/linux/centos/docker-ce.repo
+
+# 安装Docker引擎
+yum install docker-ce docker-ce-cli containerd.io
+
+# 启动Docker
+systemctl start docker
+
+# 检查Docker是否正常
+docker run hello-world
+# 列表中存在hello-world则表示正常
+docker ps
+

# 配置

# 切换仓库镜像源2

  • 对于systemd系统:Ubuntu16.04+、Debian8+、CentOS7
# 检查配置是否存在?
+ll /etc/docker/daemon.json
+# 不存在,则追加内容
+cat >> /etc/docker/daemon.json << EOF
+{"registry-mirrors":["https://docker.mirrors.ustc.edu.cn/"]}
+EOF
+# 存在,则修改内容
+vim /etc/docker/daemon.json
+# 内容如下
+# {"registry-mirrors":["https://docker.mirrors.ustc.edu.cn/"]}
+
+# 重启Docker
+systemctl daemon-reload
+systemctl restart docker
+

# 常用指令

# 开启docker服务
+service docker start
+# 启动 docker 后台服务
+systemctl start docker
+# 重启docker守护进程
+systemctl daemon-reload
+# 重启docker服务
+systemctl restart docker
+
+# 拉取镜像
+docker pull {image}:{version}
+# 查看镜像列表
+docker images
+# 删除镜像
+docker rmi {imageID}/{imageAlias}
+
+# 查看容器,不加-a查看正在运行的,加上-a查看所有
+docker ps -a
+# 移除容器
+docker rm {containerID}/{containerAlias}
+# 关闭一个已启动容器 
+docker stop {containerID}/{containerAlias}
+# 启动一个关闭的容器 
+docker start {containerID}/{containerAlias}
+# 查看一个容器的详情
+docker inspect {containerID}/{containerAlias}
+# 进入容器内部
+docker exec -it {containerID}/{containerAlias} /bin/bash
+# 生成镜像
+docker build ...
+# 运行容器
+docker run -d ... 
+

# 参考文档

  1. Docker安装 (完整详细版) (opens new window)
  2. Docker 镜像加速 (opens new window)
+ + + diff --git a/gis/data_poi_aoi_loi.html b/gis/data_poi_aoi_loi.html new file mode 100644 index 0000000..2507323 --- /dev/null +++ b/gis/data_poi_aoi_loi.html @@ -0,0 +1,33 @@ + + + + + + 「数据」POI/AOI/LOI | kite-notes + + + + + + + + + +

# 「数据」POI/AOI/LOI

# 基本概念

POI: Point of Information / Point of Interest,兴趣点,地图上非地理意义的有意义的点1泛指互联网电子地图中的点类数据2),如商铺、超市、酒店等属于POI,但像城市、山峰、河流等就不属于POI。每个POI包含四个信息:名称地址类别坐标

AOI: Area of Information / Area of Interest,兴趣面,与POI的概念类似,即互联网电子地图中的面状类数据,也同样包含四个基本信息,即名称地址类别坐标,主要在地图上表达区域状的地理实体,如小区、大学、园区等

LOI:Location of Information / Location of Interest: 兴趣位置,可以是单个/多个点/多边形,是AOIPOI更进一步的抽象。

# POI/AOI/LOI的区别与联系

正如LOI的概念所讲,LOIAOIPOI更进一步的抽象。那么可以根据LOI所包含的内容具象至AOI/POI中。

AOIPOI和关系更加的细化,AOI有着比POI更好的表现力、更好的计算力以及更长的时效性3

  • 更好的表现力:面状区域形状各异,更容易分辨区域范围
  • 更好的计算力
  • 更长的时效性POI信息瞬息万变,而AOI较稳定

POI是一切的根源,任何事物都能具象为一个点,实现降维3

# 获取POI/AOI数据1,3

# 数据坐标系问题

当前互联网地图的坐标系标准是WGS84,从GPS设备中取出的数据的坐标系,国际地图提供商使用的都是这个坐标系。

因此,我们若想使用获取的数据,那么尽量统一使用WGS84坐标系,将获取数据的进行坐标系的转换

# 火星坐标(GCJ-02)

国测局坐标系,中国标准,从国行移动设备中定位获取的坐标数据使用这个坐标系,国家规定:国内出版的各种地图系统(包括电子形式),必须至少采用GCJ-02对地理位置进行首次加密。Google国内地图(.cn域名下)腾讯搜搜、阿里系高德地图都是这个坐标系。1

# 百度坐标(BD-09)

基于火星坐标系再进行二次加密,百度提供了坐标系转换接口(百度坐标->WGS84)

# 参考文档

  1. 今天我们来谈谈POI (opens new window)

  2. POI数据介绍 (opens new window)

  3. 城市AOI数据获取教程&数据分享 (opens new window)

+ + + diff --git a/gis/index.html b/gis/index.html new file mode 100644 index 0000000..bd5a5fa --- /dev/null +++ b/gis/index.html @@ -0,0 +1,23 @@ + + + + + + GIS知识 | kite-notes + + + + + + + + + +
+ + + diff --git a/icon/kite.png b/icon/kite.png new file mode 100644 index 0000000..053d92e Binary files /dev/null and b/icon/kite.png differ diff --git a/icon/nest.png b/icon/nest.png new file mode 100644 index 0000000..ccacdcf Binary files /dev/null and b/icon/nest.png differ diff --git a/index.html b/index.html new file mode 100644 index 0000000..6f0a570 --- /dev/null +++ b/index.html @@ -0,0 +1,31 @@ + + + + + + kite-notes + + + + + + + + + +
hero

+ 鹫巢 +

+ 首页 +

+ 技术笔记 → +

简洁至上

以 Markdown 为中心的项目结构,以最少的配置帮助你专注于写作。

Vue驱动

享受 Vue + webpack 的开发体验,在 Markdown 中使用 Vue 组件,同时可以使用 Vue 来开发自定义主题。

高性能

VuePress 为每个页面预渲染生成静态的 HTML,同时在页面被加载的时候,将作为 SPA 运行。

+ + + diff --git a/myself/summary_2022.html b/myself/summary_2022.html new file mode 100644 index 0000000..eca8be1 --- /dev/null +++ b/myself/summary_2022.html @@ -0,0 +1,27 @@ + + + + + + 2022-年终总结 | kite-notes + + + + + + + + + +

# 2022-年终总结

计划赶不上变化”是今年的核心主题。虽然这句话在每个计划中都会出现,但今年让我的体会更加深刻。年初公司部门经历裁员,剩余的部分员工因被拖欠工资仓皇而逃,年底部门因运营规模缩减而将办公室回总部;我曾有新的机会改变当前状况,但最终留下与公司共克时坚,并走向了宇宙尽头;在去年想过工作赚钱比感情重要,但后来遇到了很好的她。这一切,都是自己选择的,也都将成为2022年的各种时光痕迹...

# 工作

在迷失自我中,缓慢前进...

# 工作内容/涉及范围

部门将原本的华北地区业务划分出去,今年只负责华南地区的运营。这是公司层面的运营策略调整,缩小运营规模,这无可厚非。也因此,由于我的工作表现和工作年限、以及在项目工作任务的驱动下,我在交付组从原本的一名开发人员逐渐成为了一名软件部署、系统运维人员。去接触了曾经向往但琢磨不懂的Linux系统,部署项目所需要的软件环境、修复了许多Linux等保扫漏的漏洞问题。将其过程、遇到的问题和处理方式整理归档,成为小组内的知识库。

断断续续对其他系统的功能进行开发和维护,也接触了一小部分三维相关功能的开发。

自我感觉有成就感得内容:

  1. 碎片化学习。在任务驱动下学习Linux知识,常用的基本操作指令;
  2. 自动化更新效率。编写项目级代码更新脚本,优化现场前后端代码更新效率;
  3. 尝试输出。撰写知识库,将自己遇到的问题、软件部署流程,学习笔记等内容组织归档;

# 与去年的成长对比

**一年下来,能够很明显地感受到自己的进步方向跟自己的职业规划方向大相径庭,成长速度也比远不如实习那年。**有工作内容原因,也有自我驱动原因。有句话是这么说的:“间歇性踌躇满志,持续性混吃等死”,这很符合我的目前的成长状态。

拥抱新的知识是正确的,它能够扩展我的技术视野和理解,能够让我感受到计算机世界的那种一通则通、包罗万象的快感。但如果没有真正的任务驱动,很难将了解和学习到的知识融入到自己的成长当中。同时,如果眼高手低,所有事情都了解一点,也只会一点,那就算认知再广阔,也只是一个会说话、但不会做事的人。

# 个人提升

没有量变,何以质变? 不成系统,何以通透?

# 能力提升

  1. 运维能力提升。熟悉Liunx的操作指令,了解相关文件的配置、软件安装/升级,也修复过部分系统漏洞。
  2. 公司业务熟练的提高。能够总体把握功能的前后端交互逻辑,快速定位问题,并测试排查问题。对新的需求也能够较好地完成梳理

能力的提升是多方面的。对于工作能力的提升,自我觉得在后半年渐入佳境,跟领导沟通后,明白工作任务的主次之分,着手领导安排的、时间紧的、主要需要攻克的事情;对于自我规划的能力,还是一如既往的迷茫,没有目标感,不只是这几年疫情的原因,也还有自己内心的决心不够大,总是浅尝甜头后就想着后续会容易很多,就撤下了内心的危机感,但事实并非如此,所有事情的安排都在时刻变化;对于自我提升的能力,我觉得我能坚持下来,对于短期的目标能够快速进入学习状态,工作日也能早到,能挤出大于三十分钟的时间进行自我碎片化学习,晚上下班后有时候也能够挤出一个半小时的学习时间,但唯一不好的就是有时候因为睡眠不佳,而让自己总是处于低效的学习状态中。

# 方向转变

一年的工作累计下来,方向有所改变,可能是因为公司缺人,自己逐渐变成了多面手,支持开发与运维,已经一些杂七杂八的事务。在年中的时候,自己有想过转为运维人员,但是最终还是败给了感兴趣的三维方向。同时,在九月初的时候尝试了其他机会,也获取到了新offer,但还是因为外包和薪资谈不拢的原因留在了原公司。在这次经历中,也让我感受到了“宇宙尽头”的势在必得。所以,下半年的方向就变成了备战考公...

从程序员到公务员的成长方向改变,仅管身边的朋友劝我三思,但是想到自己身处的环境,成为体制内的一员是能够给我带来最大收益的方式。于是乎开始进入紧张的2023年国考复习,剑指2023省考。虽然国考的目的只是试水,但它能够让我融入这种紧张的氛围,驱动我学习。复习过程固然是枯燥的,刷题也是,但系统学习一套理论后,所有考点都是有据可依的,难度也大。只是需要控制解题时间。所以,如果没有刷体量的增加,怎么能够提高成绩呢?,但目前个人复习的情况是,考公知识体系还不够牢固,做题速度较慢,急需提高。

# 是否能够两手抓?

曾想过开发和备战两手抓,但经过曾经的个人公考经历来看。我自己如果要考公,必须立下大决心,并脱产。相当于把自己的后路堵死,不成人便成仁。我也在下半年尝试了两手抓,确实很累,身心疲惫,即使开发压力不大,但惰性还是有的。而且,现在公司办公地点改变,每日通勤需要大量时间。因此,我很大可能会离职进行备战。

# 有何不足?如何改进?

不足:

  1. 目标感不强,容易动摇和改变。虽说涉猎了自己陌生的领域,如Linux系统,Vue2学习...但是有时候也因为学习之后对其产生了兴趣,而动摇自己的目标;
  2. 驱动力不足,容易浅尝则止。外部驱动力缺失,缺少职业任务强迫自己学习和实践;内部驱动力稍弱,易受外部因素打断而忘记继续前行;
  3. 专注力不够,容易被打断。自身睡眠不足,无精打采,容易被一些小动静打断目前做的事。

努力改进:

  1. 确定明确的大目标,并将其拆分为阶段小目标以及当前阶段需要完成的实践任务;
  2. 增强驱动力,如果没有外部驱动,那就自己驱动自己,将“以教为学”作为首要内在驱动力,一方面能过够满足内部驱动,另一方面也能够整理成知识库,分享自身收获的知识
  3. 从睡眠做起,保持良好且足够时长的睡眠,保证第二天的专注度

# 生活

出门在外,记得按时吃饭

# 人际关系

自从离开学校开始实习,和几个同学进行住得近,便进行抱团取暖,互相蹭饭吃。同学也会介绍她的朋友,也因此,我认识了她,我现在的女朋友。有了女朋友之后,我们几个同学的关系似乎加上了羁绊,关系和联系更加地密切。总是说,出门靠朋友。这句话确实不假,是他们丰富了我的日常生活,带着我玩。他们的这样的利他行为,我能不能也学习学习,链接身边的资源,实现共赢。

当公司不景气的时候,大家纷纷离职,我和剩下的几个成员通过跑步熟络了起来,一起跑完步去疯狂星期四,很快乐。但十月份的疫情和伙伴的出差,让大家都不敢在外运动,我们也减少了运动的频次

# 感情状态

  • 亲情:仅管人在异乡,但每周还是会和家人保持联系,了解家里发生的事。虽然不想回家,但对家还是有依恋的。
  • 友情:结交的伙伴越来越多啦,要学会怎么将这些资源联系起来。
  • 爱情:在朋友们的撮合之下,我俩在5.20那天确认了关系。之后便是甜甜蜜蜜的恋爱了,这种感觉很奇妙,仿佛有一个人住进了心里,关心、支持、呵护无处不在。

# 生活质量

自从年中将自己的出租屋从大单间换成一房一厅,自己更喜欢下厨,也会学会多种菜式,做给朋友品尝。有时候也觉得自己有做菜的天赋哈哈哈哈。同时,自己也会整理屋子,给自己营造舒服的环境。总体来说,生活质量逐渐变好。

+ + + diff --git a/os_linux/cmd.html b/os_linux/cmd.html new file mode 100644 index 0000000..32624d4 --- /dev/null +++ b/os_linux/cmd.html @@ -0,0 +1,101 @@ + + + + + + 常用操作 | kite-notes + + + + + + + + + +

# 常用操作

# 基本操作语法

  • & 表示衔接操作,完成操作符前的指令后立即操作后续衔接的指令
  • | 表示管道操作符,用于将该操作符前的操作返回结果作为操作符后的输入

# 用户/组操作

# 添加组
+# groupadd <opt> <group>
+# -g:指定用户组ID
+groupadd -g <gid> <group>
+
+# 添加用户
+# useradd <opt> <user>
+# -u:用户,指定用户ID
+# -g:用户组,指定用户组ID
+# -m:用户主目录
+useradd -m <mainDir> -u <uid> -g <gid> <user>
+
+# 用户附加组
+# -G: 修改用户所属的附加群组
+usermod -G <group1> [<group2>...]
+
+# 删除组
+groupdel <group>
+
+# 删除用户
+userdel <user>
+

# 文件操作

# 创建目录

# -p 表示如果不存在在新建
+mkdir -p <dirName>
+

# 创建文件

# 单纯新建文件
+touch <file>
+
+# 输出指定内容并新建
+# >:表示如果现有文件已经存在则覆盖
+echo <content> > <file>
+cat > <file>
+

# 目录/文件授权

文件权限

  • 文件类型(file-type):

    • d -> 目录
    • - -> 文件
    • l -> 表示为链接文档(link file)
    • b -> 表示为装置文件里面的可供储存的接口设备(可随机存取装置)
    • c -> 表示为装置文件里面的串行端口设备,例如键盘、鼠标(一次性读取装置)
  • rwx对照表:

    • r -> readable,权重值为4
    • w -> writeable,权重值为2
    • x -> executable,权重值为1
value permission detail
1 x 执行
2 w 写入
3 -wx 写入+执行
4 r 读取
5 r-x 读取+执行
6 rw- 读取+写入
7 rwx 读取+写入+执行
# 目录/文件赋予权限
+# 修改目录/文件所属用户与组
+# -R: 表示递归设置
+chown <user>[:<group>] [<dirName>|<fileName>]
+
+# 修改目录/文件权限
+chmod <permssion> [<dirName>|<fileName>]
+# chmod 755 file.txt
+

# 查看系统进程情况

# 查看进程是否存在(可获取进程号)
+ps -ef | grep [<key>|<port>...]
+
+# 杀死进程
+kill -9 <pid>
+

# 查看机器硬件使用情况

# 查看内存(内存总量+内存使用量+内存使用率)
+# free -k:以kb为单位,查看内存使使用情况
+# sed -n '2p':流编辑器,只输出第二行(输出那些匹配的行)
+# awk '{print $2}':每行按空格或TAB分割,输出文本中的第二项
+free -k | sed -n '2p' | awk '{print "total: "$2" KB, used: "$3" KB,used percent: "$3*100/$2"%"}'
+

# 防火墙的启动与停止

# 查看防火墙状态 
+systemctl status firewalld
+
+# 开启防火墙 
+systemctl start firewalld  
+
+# 关闭防火墙
+systemctl stop firewalld
+

# 端口检查/开放/关闭

# 查看端口是否开放
+# port: 表示端口号
+firewall-cmd --query-port=<port>/tcp
+
+# 添加指定开放端口(永久开放)
+# port: 表示端口号
+firewall-cmd --add-port=<port>/tcp --permanent
+
+# 移除指定开放端口(永久关闭)
+# port: 表示端口号
+firewall-cmd --remove-port=<port>/tcp --permanent
+
+# 端口设置生效
+firewall-cmd --reload
+
+ + + diff --git a/os_linux/index.html b/os_linux/index.html new file mode 100644 index 0000000..c3e81a8 --- /dev/null +++ b/os_linux/index.html @@ -0,0 +1,23 @@ + + + + + + Linux操作系统 | kite-notes + + + + + + + + + +
+ + + diff --git a/os_linux/operation.html b/os_linux/operation.html new file mode 100644 index 0000000..1843f35 --- /dev/null +++ b/os_linux/operation.html @@ -0,0 +1,49 @@ + + + + + + 常用操作 | kite-notes + + + + + + + + + +

# 常用操作

# 硬件挂载

# 外接硬盘挂载1,2,3

    1. 通过指令找到外接硬盘
# 列出所有硬盘信息
+fdisk -l
+

查看硬盘信息

    1. 新建需要将外接硬盘挂接到的目标目录
# 新建目录
+# 在根目录上创建数据存放的目录 ocndata
+mkdir /ocndata
+
    1. 挂载外接硬盘至目标目录
# 将磁盘路径/dev/sdb1挂载至/ocndata目录
+# mount {磁盘路径} {挂载目录}
+mount /dev/sdb1 /ocndata
+
    1. 对目标目录授予权限
# 对该目录授予最高权限
+# chmod {权限等级} {目录}
+chmod 777 /ocndata
+
    1. 设置开机自动挂载(可选,但最好进行配置)
# 编辑/ext/fstab文件
+vi /etc/fstab
+
+# 在/ext/fstab文件的最后插入一行,保存并退出
+# 说明: {磁盘路径} {挂载目录} {磁盘类型} {参数} {能否被dump备份命令作用} {是否检验扇区}
+/dev/sdb1 /ocndata ext4 defaults 0 0
+

外接硬盘自动挂载

    1. 查看挂载情况,出现该目标目录即可
df -T
+

检查目录是否存在

# 参考文档

  1. Linux挂载移动硬盘 (opens new window)

  2. linux挂载新硬盘--fdisk挂载 (opens new window)

  3. linux挂载新硬盘--parted命令 (opens new window)

+ + + diff --git a/os_linux/sh.html b/os_linux/sh.html new file mode 100644 index 0000000..f2d1ed5 --- /dev/null +++ b/os_linux/sh.html @@ -0,0 +1,187 @@ + + + + + + 常用脚本 | kite-notes + + + + + + + + + +

# 常用脚本

# JDK环境-安装+配置

# 前置条件

  1. 准备安装包。如jdk-8u261-linux-x64.tar.gz

# 脚本

主要内容:

  1. 解压jdk压缩包到指定目录,并更名
  2. 对jdk进行环境配置
  3. 测试java指令
#!/bin/bash 
+# 安装包文件(具体到文件名)
+INSTALL_PKG=/opt/soft/jdk-8u261-linux-x64.tar.gz
+# 安装目录
+INSTALL_PATH=/opt/java
+# JDK版本号
+JDK=jdk1.8.0_261
+
+echo "install jdk..."
+# 解压
+echo "tar ing..."
+mkdir $INSTALL_PATH
+tar -zxvf $INSTALL_PKG -C $INSTALL_PATH
+echo "tar end"
+
+# 配置环境变量
+echo "edit /etc/profile content"
+cat >> /etc/profile << EOF
+JAVA_HOME=$INSTALL_PATH/$JDK
+JRE_HOME=\$JAVA_HOME/
+PATH=\$PATH:\$JAVA_HOME/bin:\$JRE_HOME/bin
+CLASSPATH=.:\$JAVA_HOME/lib/dt.jar:\$JAVA_HOME/lib/tools.jar:\$JRE_HOME/lib
+export JAVA_HOME JRE_HOME PATH CLASSPATH
+EOF
+echo "edit end and source profile"
+
+# 使环境变量生效
+source /etc/profile
+echo "jdk install end"
+
+# 检查配置
+echo "test jdk"
+java -version
+

# Node环境-安装+配置

# 前置条件

  1. 准备安装包。如node-v16.15.0-linux-x64.tar

# 脚本

主要内容:

  1. 解压nodejs压缩包到指定目录,并更名
  2. 对node、npm指令进行软连接
  3. 测试node、npm指令
  4. 修改npm镜像
#!/bin/bash 
+# 安装包文件(具体到文件名)
+INSTALL_PKG=/opt/soft/node-v16.15.0-linux-x64.tar
+# 安装目录
+INSTALL_PATH=/opt/nodejs
+# JDK版本号
+NODEJS=node-v16.15.0
+
+echo "install nodejs..."
+# 解压
+echo "tar ing..."
+mkdir $INSTALL_PATH
+tar -xf $INSTALL_PKG -C $INSTALL_PATH
+mv $INSTALL_PATH/node-v16.15.0-linux-x64 $INSTALL_PATH/$NODEJS
+echo "tar end"
+
+# 软链接
+echo "build weaked link"
+ln -s $INSTALL_PATH/$NODEJS/bin/node /usr/local/bin
+ln -s $INSTALL_PATH/$NODEJS/bin/npm /usr/local/bin
+echo "build weaked link end"
+
+# 检查配置
+echo "test node"
+node -v
+echo "test npm"
+npm -v
+
+# 修改npm镜像
+npm config set registry https://registry.npm.taobao.org
+

# Maven环境-安装+配置

# 前置条件

  1. 准备安装包。如node-v16.15.0-linux-x64.tar
  2. (可选)maven配置文件(其中配置了仓库地址)。如maven-settings.xml

# 脚本

主要内容:

  1. 解压maven安装包
  2. 创建本地仓库目录
  3. (可选)替换配置文件settings.xml
  4. 写入系统环境变量
  5. 测试mvn指令
#!/bin/bash 
+# 安装包文件(具体到文件名)
+INSTALL_PKG=/home/jenkins/apache-maven-3.6.3-bin.tar.gz
+# 配置文件
+CONFIG_FILE=/opt/soft/maven-settings.xml
+# 安装目录
+INSTALL_PATH=/opt/maven
+# MAVEM版本号
+MAVEM=apache-maven-3.6.3
+
+echo "install maven..."
+# 解压
+echo "tar ing..."
+mkdir $INSTALL_PATH
+tar -zxvf $INSTALL_PKG -C $INSTALL_PATH
+echo "tar end"
+
+# 创建本地仓库目录
+echo "mkdir local repo"
+mkdir $INSTALL_PATH/$MAVEM/repo
+
+# 配置文件替换
+echo "replace file"
+if [ ! -d $CONFIG_FILE ];then
+  cp $CONFIG_FILE $INSTALL_PATH/$MAVEM/conf/settings.xml
+fi
+
+echo "edit /etc/profile content"
+cat >> /etc/profile << EOF
+MAVEN_HOME=$INSTALL_PATH/$MAVEM
+PATH=$PATH:$MAVEN_HOME/bin
+export MAVEN_HOME PATH
+EOF
+
+# 使环境变量生效
+echo "edit end and source profile"
+source /etc/profile
+echo "maven install end"
+
+# 测试
+echo "test maven"
+mvn -v
+

# Tomcat环境-安装+配置

# 前置条件

  1. JDK环境
  2. 准备安装包。如apache-tomcat-9.0.68.tar.gz

# 脚本

主要内容:

  1. 解压tomcat压缩包到指定目录
  2. 配置Tomcat自启环境变量
  3. 开放防火墙端口设置(TODO)
  4. 启动Tomcat
# 安装包文件(具体到文件名)
+INSTALL_PKG=/opt/install/apache-tomcat-9.0.68.tar.gz
+# Tomcat版本号
+TOMCAT_VER=apache-tomcat-9.0.68
+# JAVA环境
+JAVA_HOME=/opt/env/java/jdk1.8.0_351/
+# 安装目录
+INSTALL_PATH=/opt/env/tomcat
+
+echo "install tomcat..."
+# 解压
+echo "tar ing..."
+mkdir -p $INSTALL_PATH
+tar -zxf $INSTALL_PKG -C $INSTALL_PATH
+echo "tar end"
+
+# 配置自启环境变量
+echo "edit auto-started config"
+
+cat >> /etc/rc.d/rc.local << EOF
+export JAVA_HOME=$JAVA_HOME
+$INSTALL_PATH/$TOMCAT_VER/bin/startup.sh start
+EOF
+
+chmod +x /etc/rc.d/rc.local
+
+echo "auto-started config done, please reboot machine right now to take effect!!!"
+
+# 防火墙设置
+# TODO...
+
+# 启动TOMCAT
+$INSTALL_PATH/$TOMCAT_VER/bin/startup.sh start
+
+

# 检查端口号并杀死对应进程

  check_and_kill() {
+    echo "check:$1"
+    netstat -tlpn | grep "\b$1\b"
+    
+    if [ $? == 0 ]; then
+      PID=$(netstat -nlp | grep ":$1" | awk '{print $7}' | awk -F '[ / ]' '{print $1}')
+      kill -9 ${PID}
+      echo "kill:$1"
+    else
+      echo " $1 not exit"
+    fi
+  }
+  
+  # 检查并杀死指定端口号进程,可批量
+  check_and_kill 8092
+  check_and_kill 8093
+  check_and_kill 8094
+
+ + + diff --git a/os_windows/bat.html b/os_windows/bat.html new file mode 100644 index 0000000..3074f2e --- /dev/null +++ b/os_windows/bat.html @@ -0,0 +1,31 @@ + + + + + + 常用脚本 | kite-notes + + + + + + + + + +
+ + + diff --git a/os_windows/cmd.html b/os_windows/cmd.html new file mode 100644 index 0000000..7649e23 --- /dev/null +++ b/os_windows/cmd.html @@ -0,0 +1,31 @@ + + + + + + 常用指令 | kite-notes + + + + + + + + + +
+ + + diff --git a/os_windows/index.html b/os_windows/index.html new file mode 100644 index 0000000..a7805b9 --- /dev/null +++ b/os_windows/index.html @@ -0,0 +1,23 @@ + + + + + + Windows操作系统 | kite-notes + + + + + + + + + +
+ + + diff --git a/os_windows/operation.html b/os_windows/operation.html new file mode 100644 index 0000000..ada692c --- /dev/null +++ b/os_windows/operation.html @@ -0,0 +1,31 @@ + + + + + + 常用操作 | kite-notes + + + + + + + + + +
+ + +