This commit is contained in:
a624669980 2021-09-27 14:17:36 +08:00
parent 7fb9bd1d06
commit 2c1ca2b095
115 changed files with 404 additions and 12738 deletions

1
.gitignore vendored
View file

@ -27,3 +27,4 @@ gen
/sql/ /sql/
/out/ /out/
/db/ /db/
/docs/

3
.gitmodules vendored
View file

@ -1,3 +0,0 @@
[submodule "UI"]
path = UI
url = https://github.com/ZimaBoard/CasaOS-UI.git

View file

@ -7,7 +7,7 @@ build-ui:
cd UI && yarn install && yarn build cd UI && yarn install && yarn build
build-backend: build-backend:
export CGO_ENABLED=1;export CGO_LDFLAGS=-static;go mod tidy;go build -o ./casa main.go;upx --lzma --best casa export CGO_ENABLED=1;export CGO_LDFLAGS=-static;go build -o ./casa main.go;upx --lzma --best casa
help: help:
@echo "call john" @echo "call john"

View file

@ -1,3 +0,0 @@
> 1%
last 2 versions
not dead

View file

@ -1,2 +0,0 @@
// .env.dev
NODE_ENV='dev'

View file

@ -1,2 +0,0 @@
// .env.production
NODE_ENV='prod'

View file

@ -1,18 +0,0 @@
module.exports = {
root: true,
env: {
node: true
},
'extends': [
'plugin:vue/essential',
'eslint:recommended'
],
parserOptions: {
parser: 'babel-eslint'
},
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'vue/no-unused-vars':'off'
}
}

23
UI/.gitignore vendored
View file

@ -1,23 +0,0 @@
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

View file

@ -1,32 +0,0 @@
<!--
* @Author: JerryK
* @Date: 2021-09-22 14:24:43
* @LastEditors: JerryK
* @LastEditTime: 2021-09-22 14:44:31
* @Description:
* @FilePath: /CasaOS-UI/README.md
-->
# CasaOS-UI
The front-end of CasaOs,build with VueJS
## Project setup
```
yarn install
```
### Compiles and hot-reloads for development
```
yarn serve
```
### Compiles and minifies for production
```
yarn build
```
Will be output to the ../web folder
### Lints and fixes files
```
yarn lint
```

View file

@ -1,5 +0,0 @@
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}

View file

@ -1,43 +0,0 @@
{
"name": "CasaOS",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve --mode dev",
"build": "vue-cli-service build --no-clean --dest ../web --mode production",
"lint": "vue-cli-service lint"
},
"dependencies": {
"axios": "^0.21.4",
"buefy": "^0.9.0",
"core-js": "^3.6.5",
"easy-affix": "^1.0.8",
"lodash.debounce": "^4.0.8",
"lottie-vuejs": "^0.4.0",
"moment": "^2.29.1",
"nth-check": "^2.0.1",
"qs": "^6.10.1",
"vee-validate": "^3.4.12",
"vue": "^2.6.11",
"vue-router": "^3.2.0",
"vue-slider-component": "^3.2.14",
"vuex": "^3.4.0",
"vuex-persistedstate": "^4.0.0",
"yargs-parser": "^20.2.9"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-eslint": "~4.5.0",
"@vue/cli-plugin-router": "~4.5.0",
"@vue/cli-plugin-vuex": "~4.5.0",
"@vue/cli-service": "~4.5.0",
"babel-eslint": "^10.1.0",
"compression-webpack-plugin": "^9.0.0",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^6.2.2",
"node-sass": "^4.9.0",
"sass-loader": "^7.0.1",
"vue-cli-plugin-buefy": "~0.3.8",
"vue-template-compiler": "^2.6.11"
}
}

View file

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square150x150logo src="/ui/img/icon/mstile-150x150.png"/>
<TileColor>#da532c</TileColor>
</tile>
</msapplication>
</browserconfig>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 693 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6 KiB

View file

@ -1,25 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="200.000000pt" height="200.000000pt" viewBox="0 0 200.000000 200.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.14, written by Peter Selinger 2001-2017
</metadata>
<g transform="translate(0.000000,200.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M875 1894 c-11 -2 -51 -11 -88 -20 -341 -78 -610 -364 -673 -714 -82
-459 197 -902 647 -1030 94 -27 277 -37 378 -21 303 47 575 261 690 540 55
133 66 192 65 361 -1 136 -4 165 -27 235 -36 116 -62 170 -123 261 -123 186
-347 336 -566 379 -42 8 -276 15 -303 9z m250 -168 c11 -2 42 -9 70 -16 131
-30 288 -135 387 -260 160 -201 198 -506 93 -745 l-22 -50 2 80 c3 180 -64
351 -184 476 -209 216 -544 260 -807 105 -201 -117 -326 -347 -319 -587 l2
-74 -19 44 c-63 140 -80 332 -44 476 24 94 87 219 147 292 109 133 290 238
448 259 25 3 47 7 49 9 5 4 173 -3 197 -9z m8 -501 c33 -8 85 -31 116 -50 227
-137 305 -418 183 -651 l-21 -39 -1 35 c-9 251 -245 439 -490 389 -186 -38
-323 -200 -330 -389 l-1 -35 -23 45 c-101 194 -61 429 99 578 130 122 292 162
468 117z m-27 -499 c182 -85 183 -345 1 -438 -53 -27 -161 -26 -215 1 -146 75
-180 267 -69 390 63 69 190 90 283 47z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

File diff suppressed because one or more lines are too long

View file

@ -1,42 +0,0 @@
<!--
* @Author: JerryK
* @Date: 2021-09-22 14:24:43
* @LastEditors: JerryK
* @LastEditTime: 2021-09-24 18:03:02
* @Description:
* @FilePath: /CasaOS-UI/public/index.html
-->
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="apple-touch-icon" sizes="180x180" href="<%= BASE_URL %>img/icon/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="<%= BASE_URL %>img/icon/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="<%= BASE_URL %>img/icon/favicon-16x16.png">
<link rel="manifest" href="<%= BASE_URL %>site.webmanifest">
<link rel="mask-icon" href="<%= BASE_URL %>img/icon/safari-pinned-tab.svg" color="#5bbad5">
<meta name="msapplication-TileColor" content="#da532c">
<meta name="theme-color" content="#ffffff">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<link rel="stylesheet" href="//cdn.materialdesignicons.com/2.0.46/css/materialdesignicons.min.css">
<script src="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5.15.4/js/all.js"
integrity="sha256-GaerX2a/DuOnPrxn/4vH13dobiFUe/27LO6gCZDNauA=" crossorigin="anonymous"></script>
<title>
<%= htmlWebpackPlugin.options.title %>
</title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled.
Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

View file

@ -1,14 +0,0 @@
{
"name": "",
"short_name": "",
"icons": [
{
"src": "/ui/img/icon/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
}
],
"theme_color": "#ffffff",
"background_color": "#ffffff",
"display": "standalone"
}

View file

@ -1,110 +0,0 @@
<!--
* @Author: JerryK
* @Date: 2021-09-18 21:32:13
* @LastEditors: JerryK
* @LastEditTime: 2021-09-23 16:42:14
* @Description: Main entry of application
* @FilePath: /CasaOS-UI/src/App.vue
-->
<template>
<!-- <div id="app" class="is-flex is-flex-direction-column" :style="{'background-image': 'url(' + require('./assets/background/AbstractShapes.jpg') + ')'}"> -->
<div id="app" class="is-flex is-flex-direction-column" :style="{'background-image': 'url(https://www.bing.com/th?id=OHR.Aldeyjarfoss_ZH-CN0106567013_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp)'}">
<!-- NavBar Start -->
<top-bar></top-bar>
<!-- NavBar End -->
<!-- Content Start -->
<div class="contents pt-55 pb-6">
<div class="container">
<div class="is-flex">
<!-- SideBar Start -->
<side-bar></side-bar>
<!-- SideBar End -->
<!-- MainContent Start -->
<div class="main-content">
<!-- SearchBar Start -->
<section>
<search-bar></search-bar>
</section>
<!-- SearchBar End -->
<!-- Suggestions For You Start -->
<section>
<suggestion></suggestion>
</section>
<!-- Suggestions For You End -->
<!-- Apps Start -->
<section>
<apps></apps>
</section>
<!-- Apps End -->
<!-- Shortcuts Start -->
<!-- <section>
<shortcuts></shortcuts>
</section> -->
<!-- Shortcuts End -->
</div>
<!-- MainContent End -->
</div>
</div>
</div>
<!-- Content End -->
<!-- BrandBar Start -->
<brand-bar></brand-bar>
<!-- BrandBar End -->
<!-- ContactBar Start -->
<contact-bar></contact-bar>
<!-- ContactBar End -->
</div>
</template>
<script>
import Apps from './components/Apps.vue'
import BrandBar from './components/BrandBar.vue'
import ContactBar from './components/ContactBar.vue'
import SearchBar from './components/SearchBar.vue'
import SideBar from './components/SideBar.vue'
import Suggestion from './components/Suggestion.vue'
import TopBar from './components/TopBar.vue'
//import Shortcuts from './components/Shortcuts.vue'
export default {
components: {
BrandBar,
ContactBar,
SideBar,
SearchBar,
Suggestion,
Apps,
TopBar,
//Shortcuts
},
created() {
// Check if not login then login and get token
if (!localStorage.getItem("user_token")) {
this.login()
}
},
methods: {
login() {
/**
* @description: Login
* @return void
*/
// this.$api.user.login({
// username: "admin",
// pwd: "admin"
// }).then((res) => {
// if (res.data.success == 200) {
// localStorage.setItem("user_token", res.data.data)
// }
// })
}
},
}
</script>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 MiB

View file

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.2.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
<style type="text/css">
.st0{fill:none;stroke:#FFFFFF;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:2;}
</style>
<path class="st0" d="M12,22c5.5,0,10-4.5,10-10S17.5,2,12,2S2,6.5,2,12S6.5,22,12,22z"/>
<path class="st0" d="M12,22c3.9,0,7-3.1,7-7s-3.1-7-7-7s-7,3.1-7,7S8.1,22,12,22z"/>
<path class="st0" d="M12,22c2.2,0,4-1.8,4-4s-1.8-4-4-4s-4,1.8-4,4S9.8,22,12,22z"/>
</svg>

Before

Width:  |  Height:  |  Size: 729 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

View file

@ -1 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?><svg width="24" height="24" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg"><rect width="48" height="48" fill="white" fill-opacity="0.01"/><path d="M24 44C35.0457 44 44 35.0457 44 24C44 12.9543 35.0457 4 24 4C12.9543 4 4 12.9543 4 24C4 35.0457 12.9543 44 24 44Z" stroke="#333" stroke-width="4" stroke-linejoin="round"/><path d="M24 44C31.732 44 38 37.732 38 30C38 22.268 31.732 16 24 16C16.268 16 10 22.268 10 30C10 37.732 16.268 44 24 44Z" stroke="#333" stroke-width="4" stroke-linejoin="round"/><path d="M24 44C28.4183 44 32 40.4183 32 36C32 31.5817 28.4183 28 24 28C19.5817 28 16 31.5817 16 36C16 40.4183 19.5817 44 24 44Z" fill="none" stroke="#333" stroke-width="4" stroke-linejoin="round"/></svg>

Before

Width:  |  Height:  |  Size: 758 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

View file

@ -1,152 +0,0 @@
// Included below are all the defined variables from Bulma
// Modify as needed, removing the !default attribute.
// Colors
$black: hsl(0, 0%, 4%) !default;
$black-bis: hsl(0, 0%, 7%) !default;
$black-ter: hsl(0, 0%, 14%) !default;
$grey-darker: hsl(0, 0%, 21%) !default;
$grey-dark: hsl(0, 0%, 29%) !default;
$grey: hsl(0, 0%, 48%) !default;
$grey-light: hsl(0, 0%, 71%) !default;
$grey-lighter: hsl(0, 0%, 86%) !default;
$white-ter: hsl(0, 0%, 96%) !default;
$white-bis: hsl(0, 0%, 98%) !default;
$white: hsl(0, 0%, 100%) !default;
$orange: hsl(14, 100%, 53%) !default;
$yellow: hsl(48, 100%, 67%) !default;
$green: hsl(141, 71%, 48%) !default;
$turquoise: hsl(171, 100%, 41%) !default;
$cyan: hsl(204, 86%, 53%) !default;
$blue: hsl(217, 71%, 53%) !default;
$purple: hsl(271, 100%, 71%) !default;
$red: hsl(348, 100%, 61%) !default;
// Typography
$family-sans-serif: BlinkMacSystemFont, -apple-system, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", "Helvetica", "Arial", sans-serif !default;
$family-monospace: monospace !default;
$render-mode: optimizeLegibility !default;
$size-1: 3rem !default;
$size-2: 2.5rem !default;
$size-3: 2rem !default;
$size-4: 1.5rem !default;
$size-5: 1.25rem !default;
$size-6: 1rem !default;
$size-7: 0.75rem !default;
$weight-light: 300 !default;
$weight-normal: 400 !default;
$weight-medium: 500 !default;
$weight-semibold: 600 !default;
$weight-bold: 700 !default;
// Responsiveness
// The container horizontal gap, which acts as the offset for breakpoints
$gap: 32px !default;
// 960, 1152, and 1344 have been chosen because they are divisible by both 12 and 16
$tablet: 769px !default;
// 960px container + 4rem
$desktop: 960px + (2 * $gap) !default;
// 1152px container + 4rem
$widescreen: 1152px + (2 * $gap) !default;
// 1344px container + 4rem;
$fullhd: 1344px + (2 * $gap) !default;
// Miscellaneous
$easing: ease-out !default;
$radius-small: 2px !default;
$radius: 3px !default;
$radius-large: 5px !default;
$radius-rounded: 290486px !default;
$speed: 86ms !default;
// Flags
$variable-columns: true !default;
// The default Bulma derived variables are declared below
$primary: $turquoise !default;
$info: $cyan !default;
$success: $green !default;
$warning: $yellow !default;
$danger: $red !default;
$light: $white-ter !default;
$dark: $grey-darker !default;
// Invert colors
$orange-invert: findColorInvert($orange) !default;
$yellow-invert: findColorInvert($yellow) !default;
$green-invert: findColorInvert($green) !default;
$turquoise-invert: findColorInvert($turquoise) !default;
$cyan-invert: findColorInvert($cyan) !default;
$blue-invert: findColorInvert($blue) !default;
$purple-invert: findColorInvert($purple) !default;
$red-invert: findColorInvert($red) !default;
$primary-invert: $turquoise-invert !default;
$info-invert: $cyan-invert !default;
$success-invert: $green-invert !default;
$warning-invert: $yellow-invert !default;
$danger-invert: $red-invert !default;
$light-invert: $dark !default;
$dark-invert: $light !default;
// General colors
$background: $white-ter !default;
$border: $grey-lighter !default;
$border-hover: $grey-light !default;
// Text colors
$text: $grey-dark !default;
$text-invert: findColorInvert($text) !default;
$text-light: $grey !default;
$text-strong: $grey-darker !default;
// Code colors
$code: $red !default;
$code-background: $background !default;
$pre: $text !default;
$pre-background: $background !default;
// Link colors
$link: $blue !default;
$link-invert: $blue-invert !default;
$link-visited: $purple !default;
$link-hover: $grey-darker !default;
$link-hover-border: $grey-light !default;
$link-focus: $grey-darker !default;
$link-focus-border: $blue !default;
$link-active: $grey-darker !default;
$link-active-border: $grey-dark !default;
// Typography
$family-primary: $family-sans-serif !default;
$family-code: $family-monospace !default;
$size-small: $size-7 !default;
$size-normal: $size-6 !default;
$size-medium: $size-5 !default;
$size-large: $size-4 !default;

View file

@ -1,429 +0,0 @@
@import "~bulma/sass/utilities/initial-variables";
@import "~bulma/sass/utilities/functions";
// 1. Set your own initial variables and derived
// variables in _variables.scss
@import "variables";
@import url("https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;1,100;1,300;1,400;1,500;1,700&display=swap");
// 2. Setup your Custom Colors
$linkedin: #0077b5;
$linkedin-invert: findColorInvert($linkedin);
$twitter: #55acee;
$twitter-invert: findColorInvert($twitter);
$github: #333;
$github-invert: findColorInvert($github);
@import "~bulma/sass/utilities/derived-variables";
// 3. Add new color variables to the color map.
$addColors: (
"twitter": (
$twitter,
$twitter-invert,
),
"linkedin": (
$linkedin,
$linkedin-invert,
),
"github": (
$github,
$github-invert,
),
);
$colors: map-merge($colors, $addColors);
@import "~bulma";
@import "~buefy/src/scss/buefy";
$backDropColor: rgba(123, 123, 123, 0.16);
$backDropBlur: blur(1rem);
$backDropBorderRadius: 0.5rem;
// 4. Provide custom buefy overrides and site styles here
body,
html {
overflow: hidden;
font-family: "Roboto", sans-serif;
}
#app {
width: 100vw;
height: 100vh;
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
background-size: cover;
background-repeat: no-repeat;
background-position: center center;
}
.top-bar {
position: relative;
z-index: 10;
height: 3rem;
background: rgba(255, 255, 255, 0.22);
backdrop-filter: blur(180.282px);
.navbar-brand {
.dropdown-menu {
margin-top: 0.5rem;
min-width: 20rem;
.dropdown-content {
.dropdown-item {
padding: 1.25rem;
text-align: left;
.item {
height: 2rem;
}
}
}
}
}
.field {
line-height: 1rem;
}
.switch {
&.is-flex-direction-row-reverse {
.control-label {
padding-left: 0;
padding-right: calc(0.75em - 1px);
}
}
}
.update-container {
.button.is-rounded {
border-radius: 9999px !important;
padding-left: calc(1em + 0.25em);
padding-right: calc(1em + 0.25em);
}
}
.button{
&.is-small{
height: 2em;
}
}
}
.brand-bar {
position: fixed;
left: 2rem;
bottom: 2rem;
}
.contact-bar {
position: fixed;
right: 2rem;
bottom: 2rem;
height: 3.5rem;
background: rgba(0, 0, 0, 0.16);
backdrop-filter: blur(24px);
border-radius: 4px;
font-size: 1.5rem;
a {
color: $white;
margin: 0.5rem;
display: flex;
align-items: center;
&:hover {
color: #0077b5;
}
}
}
.contents {
flex: 1;
overflow: auto;
}
.side-bar {
width: 16rem;
position: fixed;
}
.main-content {
flex: 1;
margin-left: 17.5rem;
}
.pt-7 {
padding-top: 4rem;
}
.pt-55 {
padding-top: 2rem;
}
.p-55 {
padding: 2rem !important;
}
.button.is-light {
background-color: #a6afb9;
color: white;
}
.label {
font-size: 0.875rem;
margin-bottom: 0.5rem;
}
.button,
.input,
.textarea,
.taginput .taginput-container.is-focusable,
.select select,
.file-cta,
.file-name,
.pagination-previous,
.pagination-next,
.pagination-link,
.pagination-ellipsis {
&:focus {
box-shadow: none;
}
}
.image.is-72x72 {
height: 72px;
width: 72px;
}
// widgets
.widget {
background: $backDropColor;
backdrop-filter: $backDropBlur;
border-radius: $backDropBorderRadius;
padding: 0.875rem 1.5rem;
margin-bottom: 0.75rem;
}
// Cards
.wuji-card {
background: $backDropColor;
backdrop-filter: $backDropBlur;
border-radius: $backDropBorderRadius;
padding: 1.5rem;
color: $white;
position: relative;
.info {
flex: 1;
margin-right: 1rem;
color: white;
}
.simg {
img {
border-radius: 4px;
}
}
.icon-img {
position: relative;
&.stop::after {
position: absolute;
content: "";
width: 0.75rem;
height: 0.75rem;
background-color: #ff1616;
border-radius: 50%;
right: -0.375rem;
top: -0.375rem;
}
img {
border-radius: 8px;
margin: 0 auto;
}
}
.b-image-wrapper {
position: relative;
display: flex;
align-items: center;
justify-content: center;
&.stop::after {
position: absolute;
content: "";
width: 0.75rem;
height: 0.75rem;
background-color: #ff1616;
border-radius: 50%;
right: -0.375rem;
top: -0.375rem;
}
img {
border-radius: 8px;
margin: 0 auto;
}
}
.action-btn {
position: absolute;
right: 0.5rem;
top: 1rem;
visibility: hidden;
opacity: 0;
transition: all 0.2s;
}
p {
font-weight: 500;
}
.one-line {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
overflow: hidden;
}
.two-line {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
}
&:hover {
.action-btn {
visibility: visible;
opacity: 1;
}
}
a {
color: white;
p {
color: white;
}
}
}
.flex1 {
flex: 1;
}
.title-bar {
margin-bottom: 1.5rem;
.title {
flex: 1;
margin-bottom: 0;
}
}
.ii {
.dropdown-menu {
background: rgba(255, 255, 255, 0.88);
backdrop-filter: $backDropBlur;
border-radius: $backDropBorderRadius;
overflow: hidden;
padding-top: 0;
.dropdown-content {
background: none;
padding: 0;
.button {
border-radius: 0;
padding-left: 1.5rem;
padding-right: 1.5rem;
&.is-text {
text-decoration: none;
justify-content: flex-start;
outline: none;
transition: all 0.2s;
border: none !important;
&.running {
color: #779e2a !important;
}
&.exited {
color: #ff1616 !important;
}
}
&:active {
background: none;
outline: none;
}
&:focus {
background: none;
box-shadow: none;
outline: none;
}
}
.bbor {
overflow: hidden;
border-top: #2c3e50 1px solid;
.is-text {
text-decoration: none;
justify-content: center !important ;
}
.column:first-child {
border-right: #2c3e50 1px solid;
}
}
}
}
}
//Panel
.modal-background {
background: rgba(0, 0, 0, 0.8);
}
.modal-card {
background: rgba(255, 255, 255, 0.88);
backdrop-filter: $backDropBlur;
border-radius: $backDropBorderRadius;
.modal-card-head,
.modal-card-body,
.modal-card-foot {
background-color: transparent;
border: none;
}
.modal-card-head {
padding: 3rem;
}
.modal-card-body {
padding: 0 3rem;
.button.is-static,
.input,
.textarea,
.taginput .taginput-container.is-focusable,
.select select,
.file-cta,
.file-name,
.pagination-previous,
.pagination-next,
.pagination-link,
.pagination-ellipsis {
font-size: 0.875rem;
height: 2.714em;
border: 1px solid #cfcfcf !important;
border-radius: 4px;
&:focus {
box-shadow: none;
}
}
.media {
padding: 0rem;
}
.field:last-child {
margin-bottom: 0.5rem;
}
.field-body {
.field:last-child {
margin-bottom: 0rem;
}
}
.port-item:not(:last-child) {
.field {
margin-bottom: 0;
}
}
}
.modal-card-foot {
padding: 1rem 3rem 2rem 3rem;
.button {
border-radius: 9999px;
padding-left: calc(1em + 0.25em);
padding-right: calc(1em + 0.25em);
}
}
}
.import-area .textarea {
max-height: 40em;
min-height: 16em;
}
.app-card {
.loading-background {
background: none !important;
border-radius: $backDropBorderRadius;
}
}

View file

@ -1,53 +0,0 @@
<template>
<div class="widget has-text-white clock">
<div class="time">{{timeText}}</div>
<div class="data">{{dateText}}</div>
</div>
</template>
<script>
import moment from 'moment'
export default {
data() {
return {
timer: 0,
timeText:"",
dateText:""
}
},
mounted() {
if (this.timer) {
clearInterval(this.timer)
}
this.updateClock()
this.timer = setInterval(() => {
this.updateClock()
}, 1000)
},
methods: {
updateClock() {
this.timeText = moment().format('LT');
this.dateText = moment().format('dddd, MMMM Do')
}
},
}
</script>
<style lang="scss">
.clock {
font-family: Roboto;
font-style: normal;
font-weight: 300;
text-align: left;
.time {
font-size: 2.75rem;
line-height: 4.25rem;
opacity: 0.9;
}
.data {
line-height: 1.5rem;
opacity: 0.9;
}
}
</style>

View file

@ -1,16 +0,0 @@
<template>
<div class="widget has-text-white clock">
<div class="time">09:40</div>
<div class="data">WednesdaySeptember 15</div>
</div>
</template>
<script>
export default {
}
</script>
<style>
</style>

View file

@ -1,128 +0,0 @@
<!--
* @Author: JerryK
* @Date: 2021-09-18 21:32:13
* @LastEditors: JerryK
* @LastEditTime: 2021-09-18 23:01:19
* @Description: App module
* @FilePath: \CasaOS-UI\src\components\Apps.vue
-->
<template>
<div class="has-text-left mt-6">
<!-- Title Bar Start -->
<div class="title-bar is-flex is-align-items-center">
<h1 class="title is-4 has-text-white is-flex-shrink-1">Apps</h1>
<div class="buttons ">
<b-button icon-left="plus" type="is-dark" size="is-small" rounded @click="showInstall">New App</b-button>
</div>
</div>
<!-- Title Bar End -->
<!-- App List Start -->
<div class="columns is-variable is-2 is-multiline ">
<div class="column is-narrow is-3" v-for="(item,index) in appList" :key="'app-'+index">
<app-card :item="item" @updateState="getList" @configApp="showConfigPanel"></app-card>
</div>
</div>
<!-- Title Bar End -->
</div>
</template>
<script>
import AppCard from './Apps/AppCard.vue'
import Panel from './Panel.vue'
export default {
data() {
return {
appList: [],
appConfig: {}
}
},
components: {
AppCard,
},
created() {
this.getList();
},
methods: {
/**
* @description: Fetch the list of installed apps
* @return {*} void
*/
getList() {
this.$api.app.myAppList().then(res => {
this.appList = res.data.data;
})
},
/**
* @description: Show Install Panel Programmatic
* @return {*} void
*/
showInstall() {
this.$api.app.appConfig().then(res => {
if (res.data.success == 200) {
this.$buefy.modal.open({
parent: this,
component: Panel,
hasModalCard: true,
customClass: '',
trapFocus: true,
canCancel: ['escape'],
scroll: "keep",
animation: "zoom-out",
events: {
'updateState': () => {
this.getList()
}
},
props: {
id: "0",
state: "install",
configData: res.data.data
}
})
}
})
},
/**
* @description: Show Settings Panel Programmatic
* @return {*} void
*/
showConfigPanel(id) {
this.$api.app.getContainerSettingdata(id).then(ret => {
this.$api.app.appConfig().then(res => {
if (res.data.success == 200) {
this.$buefy.modal.open({
parent: this,
component: Panel,
hasModalCard: true,
customClass: '',
trapFocus: true,
canCancel: ['escape'],
scroll: "keep",
animation: "zoom-out",
events: {
'updateState': () => {
this.getList()
}
},
props: {
id: id,
state: "update",
configData: res.data.data,
initDatas: ret.data.data
}
})
}
})
})
}
}
}
</script>
<style>
</style>

View file

@ -1,202 +0,0 @@
<!--
* @Author: JerryK
* @Date: 2021-09-18 21:32:13
* @LastEditors: JerryK
* @LastEditTime: 2021-09-18 23:12:57
* @Description: App Card item
* @FilePath: \CasaOS-UI\src\components\Apps\AppCard.vue
-->
<template>
<div class="wuji-card is-flex is-align-items-center is-justify-content-center p-55 app-card" @mouseover="hover = true" @mouseleave="hover = false">
<!-- Action Button Start -->
<div class="action-btn">
<b-dropdown aria-role="list" position="is-bottom-left" class="ii" ref="dro" @active-change="setDropState">
<template #trigger>
<p role="button">
<b-icon pack="fas" icon="ellipsis-v" size="is-small">
</b-icon>
</p>
</template>
<b-dropdown-item aria-role="menu-item" :focusable="false" custom paddingless>
<b-button type="is-text" tag="a" :target="(item.state == 'running') ?'_blank':'_self'" :href="(item.state == 'running') ? siteUrl(item.port,item.index) :'javascript:void(0)'" expanded>Open</b-button>
<b-button type="is-text" @click="configApp" expanded>Setting</b-button>
<b-button type="is-text" expanded @click="uninstallConfirm" :loading="isUninstalling">Unistall</b-button>
<div class="columns is-gapless bbor">
<div class="column is-flex is-justify-content-center is-align-items-center">
<b-button icon-pack="fas" icon-left="sync" type="is-text" expanded :loading="isRestarting" @click="restartApp"></b-button>
</div>
<div class="column is-flex is-justify-content-center is-align-items-center">
<b-button icon-pack="fas" icon-left="power-off" type="is-text" expanded @click="toggle(item)" :loading="isStarting" :class="item.state"></b-button>
</div>
</div>
</b-dropdown-item>
</b-dropdown>
</div>
<!-- Action Button End -->
<!-- Card Content Start -->
<div class="has-text-centered is-flex is-justify-content-center is-flex-direction-column pt-3 pb-3">
<a :target="(item.state == 'running') ?'_blank':'_self'" class="is-flex is-justify-content-center" :href="(item.state == 'running') ? siteUrl(item.port,item.index) :'javascript:void(0)'">
<b-image :src="item.icon" :src-fallback="require('@/assets/img/default.png')" webp-fallback=".jpg" class="is-72x72" :class="item.state | dotClass"></b-image>
</a>
<p class="mt-4 one-line">
<a class="one-line" :target="(item.state == 'running') ?'_blank':'_self'" :href="(item.state == 'running') ? siteUrl(item.port,item.index) :'javascript:void(0)'">
{{item.name}}
</a>
</p>
</div>
<!-- Card Content End -->
<!-- Loading Bar Start -->
<b-loading :is-full-page="false" v-model="isUninstalling" :can-cancel="false"></b-loading>
<!-- Loading Bar End -->
</div>
</template>
<script>
export default {
name: "app-card",
data() {
return {
hover: false,
dropState: false,
isUninstalling: false,
isRestarting: false,
isStarting: false,
isStoping: false,
isSaving: false,
}
},
props: {
item: {
type: Object
},
},
methods: {
/**
* @description: Create application access link
* @param {String} port App access port
* @param {String} index App access index page
* @return {String}
*/
siteUrl(port, index) {
return (process.env.NODE_ENV === "'dev'") ? `http://${this.$store.state.devIp}:${port}${index}` : `http://${document.domain}:${port}${index}`
},
/**
* @description: Set drop-down menu status
* @param {Boolean} e
* @return {*} void
*/
setDropState(e) {
this.dropState = e
},
/**
* @description: Restart Application
* @return {*} void
*/
restartApp() {
this.isRestarting = true
this.$api.app.startContainer(this.item.custom_id, { state: "restart" }).then((res) => {
console.log(res.data);
if (res.data.success == 200) {
this.updateState()
}
this.isRestarting = false;
})
},
/**
* @description: Confirm before uninstall
* @return {*} void
*/
uninstallConfirm() {
let _this = this
this.$buefy.dialog.confirm({
title: 'Attention',
message: 'Data cannot be recovered after deletion! <br>Continue on to uninstall this application?',
type: 'is-dark',
confirmText: 'Uninstall',
onConfirm: () => {
_this.isUninstalling = true
_this.uninstallApp()
}
})
},
/**
* @description: Uninstall app
* @return {*} void
*/
uninstallApp() {
this.isUninstalling = true
this.$api.app.uninstall(this.item.custom_id).then((res) => {
if (res.data.success == 200) {
console.log(res.data.data);
this.updateState()
}
this.isUninstalling = false;
})
},
/**
* @description: Emit the event that the app has been updated
* @return {*} void
*/
updateState() {
this.$emit("updateState")
},
/**
* @description: Emit the event that the app has been updated with custom_id
* @return {*} void
*/
configApp() {
this.$emit("configApp", this.item.custom_id)
},
/**
* @description: Start or Stop a App
* @param {Object} item the app info object
* @return {*} void
*/
toggle(item) {
this.isStarting = true;
let data = {
state: item.state == "running" ? "stop" : "start"
}
this.$api.app.startContainer(item.custom_id, data).then((res) => {
console.log(res.data);
item.state = res.data.data
this.isStarting = false
this.updateState()
})
},
},
watch: {
hover(val) {
if (!val && this.dropState)
this.$refs.dro.toggle();
}
},
filters: {
/**
* @description: Format Dot Class
* @param {String} state
* @return {String}
*/
dotClass(state) {
return state == 'running' ? 'start' : 'stop'
},
}
}
</script>
<style>
</style>

View file

@ -1,27 +0,0 @@
<!--
* @Author: JerryK
* @Date: 2021-09-18 21:32:13
* @LastEditors: JerryK
* @LastEditTime: 2021-09-18 23:13:58
* @Description: The left bottom brand bar
* @FilePath: \CasaOS-UI\src\components\BrandBar.vue
-->
<template>
<div class="brand-bar is-flex is-align-items-center has-text-white">
<figure class="image is-32x32">
<img :src="require('@/assets/img/casa.svg')">
</figure>
<span class="is-size-4 mr-3 ml-3">CasaOS</span>
<span>Made by IceWhale with and you !</span>
</div>
</template>
<script>
export default {
name: "brand-bar"
}
</script>
<style>
</style>

View file

@ -1,28 +0,0 @@
<!--
* @Author: JerryK
* @Date: 2021-09-18 21:32:13
* @LastEditors: JerryK
* @LastEditTime: 2021-09-18 23:14:33
* @Description: The right bottom contact bar
* @FilePath: \CasaOS-UI\src\components\ContactBar.vue
-->
<template>
<div class="contact-bar is-flex is-align-items-center has-text-white pl-3 pr-3">
<a href="#">
<b-icon pack="fas" icon="map-signs" size=""></b-icon>
</a>
<a href="https://discord.gg/Gx4BCEtHjx" target="_blank">
<b-icon pack="fab" icon="discord" size=""></b-icon>
</a>
<a href="https://github.com/ZimaBoard/CasaOS" target="_blank">
<b-icon pack="fab" icon="github" size=""></b-icon>
</a>
</div>
</template>
<script>
export default {
name: "contact-bar"
}
</script>

View file

@ -1,453 +0,0 @@
<!--
* @Author: JerryK
* @Date: 2021-09-18 21:32:13
* @LastEditors: JerryK
* @LastEditTime: 2021-09-22 16:27:00
* @Description: Install Panel of Docker
* @FilePath: /CasaOS-UI/src/components/Panel.vue
-->
<template>
<div class="modal-card">
<!-- Modal-Card Header Start -->
<header class="modal-card-head">
<div class="flex1">
<h3 class="title is-4 has-text-weight-normal">Create a new App manually</h3>
</div>
<b-button icon-left="file-import" type="is-dark" size="is-small" rounded @click="showImportPanel" v-if="currentSlide == 1 && state == 'install'">Import</b-button>
</header>
<!-- Modal-Card Header End -->
<!-- Modal-Card Body Start -->
<section class="modal-card-body">
<section v-show="currentSlide == 1">
<ValidationObserver ref="ob1">
<ValidationProvider rules="required" name="Image" v-slot="{ errors, valid }">
<b-field label="Docker Image *" :type="{ 'is-danger': errors[0], 'is-success': valid }" :message="errors">
<b-input v-model="initData.image" placeholder="e.g.,hello-world:latest" :readonly="state == 'update'"></b-input>
<!-- <b-autocomplete :data="data" placeholder="e.g. hello-world:latest" field="image" :loading="isFetching" @typing="getAsyncData" @select="option => selected = option" v-model="initData.image" :readonly="state == 'update'"></b-autocomplete> -->
</b-field>
</ValidationProvider>
<ValidationProvider rules="required" name="Name" v-slot="{ errors, valid }">
<b-field label="App name *" :type="{ 'is-danger': errors[0], 'is-success': valid }" :message="errors">
<b-input value="" v-model="initData.label" placeholder="Your custom App Name"></b-input>
</b-field>
</ValidationProvider>
<b-field label="Icon URL">
<b-input value="" v-model="initData.icon" placeholder="Your custom icon URL"></b-input>
</b-field>
<b-field label="Web UI">
<p class="control">
<span class="button is-static">{{baseUrl}}</span>
</p>
<b-input v-model="webui" placeholder="8080/web/index.html" expanded></b-input>
</b-field>
<b-field label="Network">
<b-select v-model="initData.network_model" placeholder="Select" expanded>
<optgroup v-for="net in networks" :key="net.driver" :label="net.driver">
<option v-for="(option,index) in net.networks" :value="option.id" :key="option.name+index">
{{ option.name}}
</option>
</optgroup>
</b-select>
</b-field>
<ports v-model="initData.ports" :showHostPost="showHostPort" v-if="showPorts"></ports>
<input-group v-model="initData.volumes" label="Data Volumes" message="No App Data Volumes now, Click “+” to add one."></input-group>
<input-group v-model="initData.envs" label="Environment Variables" message="No environment variables now, Click “+” to add one." name1="Key" name2="Value"></input-group>
<input-group v-model="initData.devices" label="Devices" message="No devices now, Click “+” to add one."></input-group>
<b-field label="Memory Limit">
<vue-slider :min="256" :max="totalMemory" v-model="initData.memory"></vue-slider>
</b-field>
<b-field label="CPU Shares">
<b-select v-model="initData.cpu_shares" placeholder="Select" expanded>
<option value="10">Low</option>
<option value="50">Medium</option>
<option value="90">High</option>
</b-select>
</b-field>
<b-field label="Restart Policy">
<b-select v-model="initData.restart" placeholder="Select" expanded>
<option value="on-failure">on-failure</option>
<option value="always">always</option>
<option value="unless-stopped">unless-stopped</option>
</b-select>
</b-field>
<b-field label="App Description">
<b-input v-model="initData.description"></b-input>
</b-field>
<b-loading :is-full-page="false" v-model="isLoading" :can-cancel="false"></b-loading>
</ValidationObserver>
</section>
<section v-show="currentSlide == 2">
<div class="installing-warpper">
<lottie-animation path="./ui/img/ani/rocket-launching.json" :autoPlay="true" :width="200" :height="200"></lottie-animation>
<h3 class="title is-6 has-text-centered" :class="{'has-text-danger':errorType == 3,'has-text-black':errorType != 3}" v-html="installText"></h3>
</div>
</section>
</section>
<!-- Modal-Card Body End -->
<!-- Modal-Card Footer Start-->
<footer class="modal-card-foot is-flex is-align-items-center">
<div class="flex1"></div>
<div>
<b-button v-if="currentSlide == 1" :label="cancelButtonText" @click="$emit('close')" rounded />
<b-button v-if="currentSlide == 2 && errorType == 3 " label="Back" @click="prevStep" rounded />
<b-button v-if="currentSlide == 1 && state == 'install'" label="Install" type="is-dark" @click="installApp()" rounded />
<b-button v-if="currentSlide == 1 && state == 'update'" label="Update" type="is-dark" @click="updateApp()" rounded />
<b-button v-if="currentSlide == 2" :label="cancelButtonText" type="is-dark" @click="$emit('close')" rounded />
</div>
</footer>
<!-- Modal-Card Footer End -->
</div>
</template>
<script>
import axios from 'axios'
import InputGroup from './forms/InputGroup.vue';
import Ports from './forms/Ports.vue'
import ImportPanel from './forms/ImportPanel.vue'
import LottieAnimation from "lottie-vuejs/src/LottieAnimation.vue";
import VueSlider from 'vue-slider-component'
import 'vue-slider-component/theme/default.css'
import { ValidationObserver, ValidationProvider } from "vee-validate";
import "@/plugins/vee-validate";
import debounce from 'lodash/debounce'
export default {
components: {
Ports,
InputGroup,
ValidationObserver,
ValidationProvider,
LottieAnimation,
VueSlider
},
data() {
return {
timer: 0,
data: [],
isLoading: false,
isFetching: false,
errorType: 1,
currentSlide: 1,
cancelButtonText: "Cancel",
webui: "",
baseUrl: "",
totalMemory: 0,
networks: [],
tempNetworks: [],
networkModes: [],
installPercent: 0,
installText: "",
initData: {
port_map: "",
cpu_shares: 10,
memory: 300,
restart: "always",
label: "",
position: true,
index: "",
icon: "",
network_model: "",
image: "",
description: "",
origin: "custom",
ports: [],
volumes: [],
envs: [],
devices: [],
}
}
},
props: {
id: String,
state: String,
configData: Object,
initDatas: {
type: Object
}
},
created() {
//If it is edit, Init data
if (this.initDatas != undefined) {
this.initData = this.initDatas
this.webui = this.initDatas.port_map + this.initDatas.index
}
//Get Max memory info form device
this.totalMemory = Math.floor(this.configData.memory.total / 1048576);
this.initData.memory = this.totalMemory
//Handling network types
this.tempNetworks = this.configData.networks;
this.networkModes = this.unique(this.tempNetworks.map(item => {
return item.driver
}))
this.networks = this.networkModes.map(item => {
let tempitem = {}
tempitem.driver = item
tempitem.networks = this.tempNetworks.filter(net => {
return net.driver == item
})
return tempitem
})
let gg = this.tempNetworks.filter(item => {
if (item.driver == "bridge") {
return item
}
})
this.initData.network_model = gg[0].id
// Set Front-end base url
this.baseUrl = `${window.location.protocol}//${document.domain}:`;
},
computed: {
showPorts() {
if (this.initData.network_model.indexOf("macvlan") > -1) {
return false
} else {
return true
}
},
showHostPort() {
if (this.initData.network_model.indexOf("host") > -1) {
return false
} else {
return true
}
}
},
methods: {
/**
* @description: Process the datas before submit
* @param {*}
* @return {*} void
*/
processData() {
// GET port map and index
if (this.webui != "") {
let slashArr = this.webui.split("/")
this.initData.port_map = slashArr[0]
this.initData.index = "/" + slashArr.slice(1).join("/");
}
let model = this.initData.network_model.split("-");
this.initData.network_model = model[0]
},
/**
* @description: Array deduplication
* @param {Array} arr
* @return {Array}
*/
unique(arr) {
for (var i = 0; i < arr.length; i++) {
for (var j = i + 1; j < arr.length; j++) {
if (arr[i] == arr[j]) {
arr.splice(j, 1);
j--;
}
}
}
return arr;
},
/**
* @description: Back to prev Step
* @param {*}
* @return {*} void
*/
prevStep() {
this.currentSlide--;
},
/**
* @description: Validate form async
* @param {Object} ref ref of component
* @return {Boolean}
*/
async checkStep(ref) {
let isValid = await ref.validate()
return isValid
},
/**
* @description: Submit datas after valid
* @param {*}
* @return {*} void
*/
installApp() {
this.checkStep(this.$refs.ob1).then(val => {
if (val) {
this.processData();
this.isLoading = true;
this.$api.app.install(this.id, this.initData).then((res) => {
this.isLoading = false;
if (res.data.success == 200) {
this.currentSlide = 2;
this.cancelButtonText = "Continue in background"
this.checkInstallState(res.data.data)
} else {
//this.currentSlide = 1;
this.$buefy.toast.open({
message: res.data.message,
type: 'is-warning'
})
}
})
}
})
},
/**
* @description: Check the installation process every 250 milliseconds
* @param {String} appId
* @return {*} void
*/
checkInstallState(appId) {
this.timer = setInterval(() => {
this.updateInstallState(appId)
}, 250)
},
/**
* @description: Update the installation status to the UI
* @param {String} appId
* @return {*} void
*/
updateInstallState(appId) {
this.$api.app.state(appId).then((res) => {
let resData = res.data.data;
this.installPercent = resData.speed;
this.errorType = resData.type;
if (this.errorType == 4) {
try {
let info = JSON.parse(resData.message)
let id = (info.id != undefined) ? info.id : "";
let progress = ""
if (info.progressDetail != undefined) {
let progressDetail = info.progressDetail
if (!isNaN(progressDetail.current / progressDetail.total)) {
progress = "<br>Progress:" + String(Math.floor((progressDetail.current / progressDetail.total) * 100)) + "%"
}
}
let status = info.status
this.installText = status + ":" + id + " " + progress
} catch (error) {
console.log(error);
}
} else {
this.installText = resData.message
}
if (resData.speed == 100 || this.errorType == 3) {
clearInterval(this.timer)
}
let _this = this
if (resData.speed == 100) {
setTimeout(() => {
_this.$emit('updateState')
_this.$emit('close')
}, 1000)
}
})
},
/**
* @description: Save edit update
* @return {*} void
*/
updateApp() {
this.processData();
this.isLoading = true;
this.$api.app.updateContainerSetting(this.id, this.initData).then((res) => {
if (res.data.success == 200) {
this.isLoading = false;
this.$emit('updateState')
} else {
this.$buefy.toast.open({
message: res.data.message,
type: 'is-warning'
})
}
this.$emit('close')
})
},
/**
* @description: Show import panel
* @return {*} void
*/
showImportPanel() {
this.$buefy.modal.open({
parent: this,
component: ImportPanel,
hasModalCard: true,
customClass: '',
trapFocus: true,
canCancel: ['escape'],
scroll: "keep",
animation: "zoom-out",
events: {
'update': (e) => {
this.initData = e
this.$buefy.dialog.alert({
title: 'Attention',
message: 'AutoFill only helps you to complete most of the configuration. Some of the configuration information still needs to be confirmed by you.',
type: 'is-dark'
})
}
},
props: {
initData: this.initData,
netWorks: this.networks
}
})
},
/**
* @description: Get remote synchronization information
* @param {*} function
* @return {*} void
*/
getAsyncData: debounce(function (name) {
if (!name.length) {
this.data = []
return
}
this.isFetching = true
axios.get(`https://hub.docker.com/api/content/v1/products/search?source=community&q=${name}&page=1&page_size=4`)
.then(({ data }) => {
this.data = []
data.summaries.forEach((item) => this.data.push(item.name))
})
.catch((error) => {
this.data = []
throw error
})
.finally(() => {
this.isFetching = false
})
}, 500)
},
destroyed() {
clearInterval(this.timer)
},
}
</script>

View file

@ -1,105 +0,0 @@
<!--
* @Author: JerryK
* @Date: 2021-09-18 21:32:13
* @LastEditors: JerryK
* @LastEditTime: 2021-09-19 09:23:01
* @Description: Top Search bar
* @FilePath: \CasaOS-UI\src\components\SearchBar.vue
-->
<template>
<b-field position="is-centered " class="search-bar has-text-white">
<b-input placeholder="Google Search..." v-model="keyText" icon="magnify" icon-right="magnify" icon-right-clickable @icon-right-click="gotoSearch" @keyup.enter.native="gotoSearch" size="is-large" :class="['ovh',isFocus?'fo':'']" expanded @focus="onFocus" @blur="onBlur">
</b-input>
</b-field>
</template>
<script>
export default {
name: "search-bar",
data() {
return {
isFocus: false,
keyText: ""
}
},
methods: {
/**
* @description: Handle Focus event
* @return {*} void
*/
onFocus() {
this.isFocus = true;
},
/**
* @description: Handle Blur event
* @return {*} void
*/
onBlur() {
if (this.keyText == "")
this.isFocus = false;
},
/**
* @description: Pop up a new window and jump to google search
* @return {*} void
*/
gotoSearch() {
window.open("https://www.google.com/search?q=" + this.keyText, '_blank')
}
},
}
</script>
<style lang="scss">
.search-bar {
input {
transition: all 0.2s;
appearance: none;
background: rgba(123, 123, 123, 0.16);
backdrop-filter: blur(0.875rem);
border-radius: 8px;
border: none;
outline: none;
font-size: 1.5rem;
color: white;
&:focus {
border: none;
box-shadow: none;
}
&::placeholder {
color: white;
}
}
.ovh {
overflow: hidden;
.icon.is-left {
transition: all 0.2s;
left: 0;
}
.icon.is-right {
transition: all 0.2s;
right: -3rem !important;
color: white !important;
}
input {
padding-left: 2.5em !important;
padding-right: 1em !important;
}
}
.fo {
.icon.is-left {
left: -3rem !important;
}
.icon.is-right {
transition: all 0.2s;
right: 0 !important;
}
input {
padding-right: 2.5em !important;
padding-left: 1em !important;
}
}
}
</style>

View file

@ -1,56 +0,0 @@
<!--
* @Author: JerryK
* @Date: 2021-09-18 21:32:13
* @LastEditors: JerryK
* @LastEditTime: 2021-09-19 09:23:49
* @Description:
* @FilePath: \CasaOS-UI\src\components\Shortcuts.vue
-->
<template>
<div class="has-text-left mt-6">
<div class="title-bar is-flex is-align-items-center">
<h1 class="title is-4 has-text-white is-flex-shrink-1">Shortcuts</h1>
<div class="buttons ">
<b-button icon-left="plus" type="is-dark" size="is-small" rounded>Add shortcut</b-button>
</div>
</div>
<div class="columns is-variable is-2 is-multiline ">
<div class="column is-narrow is-3" v-for="n in 10" :key="n">
<div class="wuji-card is-flex is-align-items-center ">
<figure class="image is-32x32 simg">
<img :src="require('@/assets/img/icon.png')">
</figure>
<p class="ml-4 flex1 one-line">Test</p>
<div class="action-btn1">
<b-dropdown aria-role="list" position="is-bottom-left" append-to-body>
<template #trigger>
<p role="button">
<b-icon pack="fas" icon="ellipsis-v" size="is-small">
</b-icon>
</p>
</template>
<b-dropdown-item aria-role="listitem">Action</b-dropdown-item>
<b-dropdown-item aria-role="listitem">Another action</b-dropdown-item>
<b-dropdown-item aria-role="listitem">Something else</b-dropdown-item>
</b-dropdown>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'shortcuts'
}
</script>
<style>
</style>

View file

@ -1,27 +0,0 @@
<!--
* @Author: JerryK
* @Date: 2021-09-18 21:32:13
* @LastEditors: JerryK
* @LastEditTime: 2021-09-18 23:20:56
* @Description:
* @FilePath: \CasaOS-UI\src\components\SideBar.vue
-->
<template>
<div class="side-bar mr-5">
<clock></clock>
</div>
</template>
<script>
import Clock from '../assets/widgets/Clock.vue'
export default {
name: 'side-bar',
components: { Clock },
}
</script>
<style>
</style>

View file

@ -1,55 +0,0 @@
<!--
* @Author: JerryK
* @Date: 2021-09-18 21:32:13
* @LastEditors: JerryK
* @LastEditTime: 2021-09-18 23:20:19
* @Description:
* @FilePath: \CasaOS-UI\src\components\Suggestion.vue
-->
<template>
<div class="has-text-left ">
<h1 class="title is-4 mt-6 has-text-white">Suggestions</h1>
<div class="columns is-variable is-2 is-multiline">
<div class="column is-one-third" v-for="(item,index) in list" :key="'ss'+index">
<a :href="item.url" target="_blank">
<div class="wuji-card is-flex is-align-items-center">
<div class="info ">
<div class="two-line ">
{{item.title}}
</div>
<div class="des two-line">
{{item.content}}
</div>
</div>
<figure class="image is-48x48 simg is-flex">
<img :src="item.image_url">
</figure>
</div>
</a>
</div>
</div>
</div>
</template>
<script>
export default {
name:'suggestion',
data() {
return {
list: []
}
},
mounted() {
this.$api.task.list().then(res => {
if (res.data.success == 200) {
this.list = res.data.data
}
})
},
}
</script>
<style>
</style>

View file

@ -1,161 +0,0 @@
<!--
* @Author: JerryK
* @Date: 2021-09-18 21:32:13
* @LastEditors: JerryK
* @LastEditTime: 2021-09-23 18:21:13
* @Description: Top bar
* @FilePath: /CasaOS-UI/src/components/TopBar.vue
-->
<template>
<div class="navbar top-bar is-flex is-align-items-center">
<div class="navbar-brand ml-3">
<b-dropdown aria-role="list" class="navbar-item" @active-change="onOpen">
<template #trigger>
<p role="button">
<b-icon pack="fas" icon="sliders-h">
</b-icon>
</p>
</template>
<b-dropdown-item aria-role="menu-item" :focusable="false" custom>
<h2 class="title is-4">CasaOS Setting</h2>
<div class="is-flex is-align-items-center item">
<div class="is-flex is-align-items-center flex1">
<b-icon pack="fas" icon="sync-alt" class="mr-1"></b-icon> <b>Update</b>
</div>
<div>
v{{updateInfo.current_version}}
</div>
<!-- <b-field>
<b-switch v-model="barData.auto_update" type="is-dark" size="is-small" class="is-flex-direction-row-reverse mr-0" @input="saveData">
Auto-Check
</b-switch>
</b-field> -->
</div>
<div class="is-flex is-align-items-center pl-5" v-if="!updateInfo.is_need">
{{latestText}}
<b-icon type="is-success" pack="fas" icon="check" class="ml-1"></b-icon>
</div>
<div class="is-flex is-align-items-center is-justify-content-end update-container pl-5" v-if="updateInfo.is_need">
<div class="flex1">{{updateText}}</div>
<b-button type="is-dark" size="is-small" class="ml-2" :loading="isUpdating" rounded @click="updateSystem">Update</b-button>
</div>
</b-dropdown-item>
</b-dropdown>
</div>
<div class="navbar-menu">
<div class="navbar-end mr-3">
<!-- <b-icon pack="far" icon="comment-alt"></b-icon> -->
</div>
</div>
</div>
</template>
<script>
export default {
name: "top-bar",
data() {
return {
timer: 0,
barData: {
auto_update: false,
background: "",
background_type: "d",
search_engine: "google",
search_switch: false,
shortcuts_switch: false,
widgets_switch: false
},
updateInfo: {
current_version: '0',
is_need: false,
version: Object
},
isUpdating: false,
latestText: "Currently the latest version",
updateText: "A new version is available!"
}
},
created() {
this.getConfig();
},
methods: {
/**
* @description: Get CasaOs Configs
* @return {*} void
*/
getConfig() {
this.$api.info.systemConfig().then(res => {
if (res.data.success == 200) {
this.barData = res.data.data
}
})
},
/**
* @description: Save CasaOs Configs
* @return {*} void
*/
saveData() {
this.$api.info.saveSystemConfig(this.barData).then(res => {
if (res.data.success == 200) {
console.log(res);
}
})
},
/**
* @description: Handle Dropmenu state
* @param {Boolean} isOpen
* @return {*} void
*/
onOpen(isOpen) {
if (isOpen) {
this.$api.info.checkVersion().then(res => {
if (res.data.success == 200) {
this.updateInfo = res.data.data
}
})
}
},
/**
* @description: Update System Version and check update state
* @return {*} void
*/
updateSystem() {
this.isUpdating = true;
this.$api.info.updateSystem().then(res => {
if (res.data.success == 200) {
console.log(res.data.data);
}
});
this.checkUpdateState();
},
/**
* @description: check update state if is_need is false then reload page
* @return {*} void
*/
checkUpdateState() {
this.timer = setInterval(() => {
this.$api.info.checkVersion().then(res => {
if (res.data.success == 200) {
if (!res.data.data.is_need) {
clearInterval(this.timer);
location.reload();
}
}
})
}, 3000)
}
},
}
</script>

View file

@ -1,154 +0,0 @@
<template>
<div class="modal-card">
<!-- Modal-Card Header Start -->
<header class="modal-card-head">
<div class="flex1">
<h3 class="title is-4 has-text-weight-normal">Import From Docker CLI</h3>
</div>
</header>
<!-- Modal-Card Header End -->
<!-- Modal-Card Body Start -->
<section class="modal-card-body">
<b-field label="Command Line" :type="{ 'is-danger': parseError}" :message="errors">
<b-input maxlength="800" type="textarea" class="import-area" v-model="dockerCliCommands"></b-input>
</b-field>
</section>
<!-- Modal-Card Body End -->
<!-- Modal-Card Footer Start-->
<footer class="modal-card-foot is-flex is-align-items-center">
<div class="flex1"></div>
<div>
<b-button label="Cancel" @click="$emit('close')" rounded />
<b-button label="Sumbit" type="is-dark" @click="emitSubmit" rounded />
</div>
</footer>
<!-- Modal-Card Footer End -->
</div>
</template>
<script>
import parser from 'yargs-parser'
export default {
data() {
return {
dockerCliCommands: "",
parseError: false,
errors: "",
}
},
props: {
initData: Object,
netWorks: Array
},
created() {
console.log(this.netWorks);
},
methods: {
/**
* @description: Emit Event to tell parent Update
* @param {*}
* @return {*} void
*/
emitSubmit() {
if (this.parseCli()) {
this.errors = ""
this.$emit('update', this.initData)
this.$emit('close')
} else {
this.errors = "Please fill correct command line"
this.parseError = true;
}
},
/**
* @description: Parse Import Docker Cli Commands
* @return {Boolean}
*/
parseCli() {
const formattedInput = this.dockerCliCommands.replace(/\<[^\>]*\>/g, 'Custom_data').replace(/[\r\n]/g, "").replace(/\\/g, "\\ ").trim();
const parsedInput = parser(formattedInput)
console.log(parsedInput);
const { _: command, ...params } = parsedInput;
if (command[0] !== 'docker' || (command[1] !== 'run' && command[1] !== 'create')) {
return false
} else {
//Envs
this.initData.envs = this.makeArray(parsedInput.e).map(item => {
let ii = item.split("=");
return {
container: ii[0],
host: ii[1]
}
})
//Ports
this.initData.ports = this.makeArray(parsedInput.p).map(item => {
let pArray = item.split(":")
let endArray = pArray[1].split("/")
let protocol = (endArray[1]) ? endArray[1] : 'tcp';
return {
container: endArray[0],
host: pArray[0],
protocol: protocol
}
})
//Volume
this.initData.volumes = this.makeArray(parsedInput.v).map(item => {
let ii = item.split(":");
return {
container: ii[1],
host: ii[0]
}
})
// Devices
this.initData.devices = this.makeArray(parsedInput.device).map(item => {
let ii = item.split(":");
return {
container: ii[1],
host: ii[0]
}
})
//Network
if (parsedInput.network != undefined) {
let network = (parsedInput.network == 'physical') ? 'macvlan' : parsedInput.network;
let seletNetworks = this.netWorks.filter(item => {
if (item.driver == network) {
return true
}
})
if (seletNetworks.length > 0) {
this.initData.network_model = seletNetworks[0].networks[0].id;
}
}
//Image
this.initData.image = [...command].pop()
//Label
if (parsedInput.name != undefined) {
this.initData.label = parsedInput.name.replace(/^\S/, s => s.toUpperCase())
}
//Restart
if (parsedInput.restart != undefined) {
this.initData.restart = parsedInput.restart
}
return true
}
},
/**
* @description: Make String to Array
* @param {*}
* @return {Array}
*/
makeArray(foo) {
let newArray = (typeof (foo) == "string") ? [foo] : foo
return (newArray == undefined) ? [] : newArray
}
},
}
</script>
<style>
</style>

View file

@ -1,108 +0,0 @@
<template>
<div class="mb-5">
<div class="field is-flex is-align-items-center mb-2">
<label class="label mb-0 flex1">{{label}}</label>
<b-button icon-left="plus" type="is-dark" size="is-small" rounded @click="addItem">Add</b-button>
</div>
<div class="is-flex is-align-items-center mb-5 info" v-if="vdata.length == 0">
<b-icon pack="fas" icon="info-circle" size="is-small" class="mr-2 "></b-icon>
<span>
{{message}}
</span>
</div>
<div class="port-item" v-for="(item,index) in vdata" :key="'port'+index">
<b-icon pack="fas" icon="times" size="is-small" class="is-clickable" @click.native="removeItem(index)"></b-icon>
<template v-if="index < 1">
<b-field grouped>
<b-field :label="name1" expanded>
<b-input :placeholder="name1" v-model="item.container" expanded @input="handleInput"></b-input>
</b-field>
<b-field :label="name2" expanded>
<b-input :placeholder="name2" v-model="item.host" expanded @input="handleInput"></b-input>
</b-field>
</b-field>
</template>
<template v-else>
<b-field grouped>
<b-input :placeholder="name1" v-model="item.container" expanded @input="handleInput"></b-input>
<b-input :placeholder="name2" v-model="item.host" expanded @input="handleInput"></b-input>
</b-field>
</template>
</div>
</div>
</template>
<script>
export default {
name:'input-group',
data() {
return {
isLoading: false,
items: [],
min: 0
}
},
model: {
prop: 'vdata',
event: 'change'
},
props: {
vdata: Array,
label: String,
message: String,
name1: {
type: String,
default: "Container"
},
name2: {
type: String,
default: "Host"
},
},
created() {
//this.items = this.vdata;
},
watch: {
},
mounted() {
//this.addItem()
},
methods: {
addItem() {
let itemObj = {
container: "",
host: ""
}
this.vdata.push(itemObj)
},
removeItem(index) {
this.vdata.splice(index, 1)
this.filterArray()
},
handleInput() {
this.filterArray()
},
filterArray() {
// let newArray = this.items.filter(item => {
// if (item.container != "" && item.host != "") {
// return true
// } else {
// return false
// }
// })
this.$emit('change', this.vdata)
}
},
}
</script>

View file

@ -1,134 +0,0 @@
<template>
<div class="mb-5">
<div class="field is-flex is-align-items-center mb-2">
<label class="label mb-0 flex1">Ports</label>
<b-button icon-left="plus" type="is-dark" size="is-small" rounded @click="addItem">Add</b-button>
</div>
<div class="is-flex is-align-items-center mb-5 info" v-if="vdata.length == 0">
<b-icon pack="fas" icon="info-circle" size="is-small" class="mr-2 "></b-icon>
<span>
No App Ports now, Click + to add one.
</span>
</div>
<div class="port-item" v-for="(item,index) in vdata" :key="'port'+index">
<b-icon pack="fas" icon="times" size="is-small" class="is-clickable" @click.native="removeItem(index)"></b-icon>
<template v-if="index < 1">
<b-field grouped>
<b-field label="Container" expanded>
<b-input placeholder="Container" type="number" v-model="item.container" expanded @input="handleInput"></b-input>
</b-field>
<b-field label="Host" expanded>
<b-input placeholder="Host" type="number" v-model="item.host" expanded @input="handleInput" v-if="showHostPost"></b-input>
</b-field>
<b-field label="Protocol" expanded>
<b-select placeholder="Protocol" v-model="item.protocol" expanded @input="handleInput">
<option value="tcp">TCP</option>
<option value="udp">UDP</option>
<option value="both">TCP + UDP</option>
</b-select>
</b-field>
</b-field>
</template>
<template v-else>
<b-field grouped>
<b-input placeholder="Container" type="number" v-model="item.container" expanded @input="handleInput"></b-input>
<b-input placeholder="Host" type="number" v-model="item.host" expanded @input="handleInput" v-if="showHostPost"></b-input>
<b-select placeholder="Protocol" v-model="item.protocol" expanded @input="handleInput">
<option value="tcp">TCP</option>
<option value="udp">UDP</option>
<option value="both">TCP + UDP</option>
</b-select>
</b-field>
</template>
</div>
</div>
</template>
<script>
export default {
name: 'ports',
data() {
return {
isLoading: false,
items: [],
min: 0
}
},
model: {
prop: 'vdata',
event: 'change'
},
props: {
vdata: Array,
showHostPost: Boolean
},
created() {
//this.items = this.vdata;
},
mounted() {
if (this.vdata.length == 0) {
//this.addItem()
}
},
methods: {
addItem() {
let itemObj = {
container: "",
host: "",
protocol: "tcp"
}
this.vdata.push(itemObj)
},
removeItem(index) {
this.vdata.splice(index, 1)
this.filterArray()
},
handleInput() {
this.filterArray()
},
filterArray() {
// let newArray = this.items.filter(item => {
// if (item.container != "" && item.host != "") {
// return true
// } else {
// return false
// }
// })
this.$emit('change', this.vdata)
}
},
}
</script>
<style lang="scss">
.info {
font-size: 0.875rem;
color: #5a5a5a;
}
.port-item {
position: relative;
.icon {
position: absolute;
right: -1.5rem;
bottom: 0.825rem;
}
&:not(:last-child) {
margin-bottom: 0.5rem;
}
.field.is-expanded {
.label {
text-align: center;
font-weight: normal;
}
}
}
</style>

View file

@ -1,17 +0,0 @@
import Vue from 'vue'
import App from '@/App.vue'
import router from '@/router'
import store from '@/store'
import api from '@/service/api.js'
import Buefy from 'buefy'
import '@/assets/scss/app.scss'
Vue.use(Buefy)
Vue.config.productionTip = false
Vue.prototype.$api = api;
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')

View file

@ -1,28 +0,0 @@
import { required, confirmed, length, email, min } from "vee-validate/dist/rules";
import { extend } from "vee-validate";
extend("required", {
...required,
message: "This field is required"
});
extend("email", {
...email,
message: "This field must be a valid email"
});
extend("confirmed", {
...confirmed,
message: "This field confirmation does not match"
});
extend("length", {
...length,
message: "This field must have 2 options"
});
extend("min", {
...min,
message: "This field must have more than {length} characters"
});

View file

@ -1,24 +0,0 @@
/*
* @Author: JerryK
* @Date: 2021-09-18 21:32:13
* @LastEditors: JerryK
* @LastEditTime: 2021-09-18 23:19:27
* @Description:
* @FilePath: \CasaOS-UI\src\router\index.js
*/
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const routes = [
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router

View file

@ -1,19 +0,0 @@
/*
* @Author: JerryK
* @Date: 2021-09-18 21:32:13
* @LastEditors: JerryK
* @LastEditTime: 2021-09-23 15:59:52
* @Description:
* @FilePath: /CasaOS-UI/src/service/api.js
*/
import user from "./user.js";
import app from './app.js';
import task from './task.js';
import info from './info.js';
export default {
app,
info,
user,
task
}

View file

@ -1,79 +0,0 @@
/*
* @Author: JerryK
* @Date: 2021-09-18 21:32:13
* @LastEditors: JerryK
* @LastEditTime: 2021-09-19 09:26:20
* @Description: Application API
* @FilePath: \CasaOS-UI\src\service\app.js
*/
import { api } from "./service.js";
const app = {
//Get Install Info
appConfig() {
return api.get("/app/install/config");
},
//Store List
storeList(data) {
return api.get("/app/list", data);
},
//Store App Info
storeAppInfo(id) {
return api.get("/app/appinfo/" + id);
},
//Store Category List
storeCategoryList() {
return api.get("/app/category");
},
//Check Port
checkPort(port, type) {
let data = {
type: type
}
return api.get('/app/check/' + port, data);
},
// Get a free port
getPort() {
return api.get('/app/getport');
},
// Get app Running State
getState(id, data) {
return api.get('/app/state/' + id, data);
},
//Install App
install(id, data) {
return api.post('/app/install/' + id, data);
},
//Install Info
state(id) {
return api.get('/app/speed/' + id);
},
// Uninstall App
uninstall(id) {
return api.delete('/app/uninstall/' + id);
},
//My App List
myAppList(data) {
return api.get('/app/mylist', data);
},
//Container info
getContainerInfo(id) {
return api.get('/app/info/' + id);
},
//Container Log
getContainerLogs(id) {
return api.get('/app/logs/' + id)
},
//Start Or Stop Or Restart A Container with ID
startContainer(id, data) {
return api.put('/app/state/' + id, data)
},
getContainerSettingdata(id) {
return api.get(`/app/update/${id}/info`)
},
//Update Container Settings
updateContainerSetting(id, data) {
return api.put(`/app/update/${id}/setting`, data);
}
}
export default app;

View file

@ -1,37 +0,0 @@
/*
* @Author: JerryK
* @Date: 2021-09-18 21:32:13
* @LastEditors: JerryK
* @LastEditTime: 2021-09-19 09:26:08
* @Description: DDNS Service API
* @FilePath: \CasaOS-UI\src\service\ddns.js
*/
import { api } from "./service.js";
const ddns = {
//Add New DDNS
add(data) {
return api.post("/ddns/set", data);
},
//Delete a DDNS Item
delete(id) {
return api.delete("/ddns/delete/" + id);
},
//Get DDNS List
get_list() {
return api.get('/ddns/list');
},
//Ger DDNS Provider List
get_provider_list() {
return api.get('/ddns/getlist');
},
//Get Public Internet IP address (IPv4)
get_ipv4() {
return api.get('/ddns/ip');
},
// Ping Host
ping(host) {
return api.get('/ddns/ping/' + host);
}
}
export default ddns;

View file

@ -1,35 +0,0 @@
/*
* @Author: JerryK
* @Date: 2021-09-18 21:32:13
* @LastEditors: JerryK
* @LastEditTime: 2021-09-19 09:26:02
* @Description: Disk API
* @FilePath: \CasaOS-UI\src\service\disk.js
*/
import { api } from "./service.js";
const disk = {
// get Path list
diskInfo() {
return api.get('/disk/info');
},
diskList() {
return api.get('/disk/list');
},
// System path
renamePath(oldpath, path) {
let data = {
oldpath: oldpath,
newpath: path
}
return api.get('/zima/rename', data);
},
// Make a new Dir
mkdir(path) {
let data = {
path: path
}
return api.get('/zima/mkdir', data)
}
}
export default disk;

View file

@ -1,36 +0,0 @@
/*
* @Author: JerryK
* @Date: 2021-09-18 21:32:13
* @LastEditors: JerryK
* @LastEditTime: 2021-09-19 09:25:53
* @Description: File API
* @FilePath: \CasaOS-UI\src\service\file.js
*/
import { api } from "./service.js";
const file = {
// get Path list
dirPath(path) {
let data = {
path: path
}
return api.get('/file/dirpath', data);
},
// System path
renamePath(oldpath, path) {
let data = {
oldpath: oldpath,
newpath: path
}
return api.get('/file/rename', data);
},
// Make a new Dir
mkdir(path) {
let data = {
path: path
}
return api.post('/file/mkdir', data)
}
}
export default file;

View file

@ -1,53 +0,0 @@
/*
* @Author: JerryK
* @Date: 2021-09-18 21:32:13
* @LastEditors: JerryK
* @LastEditTime: 2021-09-23 17:41:01
* @Description: System HardWare Info API
* @FilePath: /CasaOS-UI/src/service/info.js
*/
import { api } from "./service.js";
const info = {
//CPU info
cpuInfo() {
return api.get("/zima/getcpuinfo");
},
//Memory Info
memoryInfo() {
return api.get("/zima/getmeminfo");
},
//Network Info
networkInfo() {
return api.get('/zima/getnetinfo');
},
//Disk Info
diskInfo() {
return api.get('/zima/getdiskinfo');
},
//All Info
allInfo() {
return api.get('/zima/getinfo');
},
// System Info
systemInfo() {
return api.get('/zima/sysinfo');
},
//Get CasaOS Config
systemConfig() {
return api.get('/sys/config')
},
//Save CasaOs Config
saveSystemConfig(data) {
return api.post('/sys/config', data)
},
// Check Verison
checkVersion() {
return api.get('/sys/check');
},
//Update System
updateSystem(){
return api.post('/sys/update');
}
}
export default info;

View file

@ -1,138 +0,0 @@
/*
* @Author: JerryK
* @Date: 2021-09-18 21:32:13
* @LastEditors: JerryK
* @LastEditTime: 2021-09-23 17:26:31
* @Description:
* @FilePath: /CasaOS-UI/src/service/service.js
*/
import axios from 'axios'
import qs from 'qs'
import router from '@/router'
import store from '@/store'
// Set Post Headers
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8';
axios.defaults.withCredentials = false;
if (process.env.NODE_ENV === "'dev'") {
axios.defaults.baseURL = `http://${store.state.devIp}:8089/v1`;
} else {
axios.defaults.baseURL = `${document.location.protocol}//${document.location.host}/v1`
}
//Create a axios instance, And set timeout to 30s
const instance = axios.create({
timeout: 10000,
});
window.isRefreshing = false
let refreshSubscribers = []
function subscribeTokenRefresh(cb) {
refreshSubscribers.push(cb)
}
function onRrefreshed(token) {
refreshSubscribers.map(cb => cb(token))
}
// Request interceptors
instance.interceptors.request.use((config) => {
let token = ''
if (sessionStorage.getItem("user_token")) {
token = sessionStorage.getItem("user_token")
}
if (localStorage.getItem("user_token")) {
token = localStorage.getItem("user_token")
}
config.headers.Authorization = token
if (token === "" && config.url !== "user/login") {
if (!window.isRefreshing) {
window.isRefreshing = true;
axios.post('user/login', qs.stringify({
username: "admin",
pwd: "admin"
})).then(res => {
token = res.data.data;
store.commit('setToken', token)
localStorage.setItem("user_token", token)
onRrefreshed(token);
})
}
let retry = new Promise((resolve) => {
/* (token) => {...}这个函数就是回调函数 */
subscribeTokenRefresh((token) => {
config.headers.Authorization = token
/* 将请求挂起 */
resolve(config)
})
})
return retry
} else {
return config;
}
}, (error) => {
// Do something with request error
return Promise.reject(error)
})
// 响应拦截(请求返回后拦截)
instance.interceptors.response.use(response => {
//console.log("响应拦截", response);
return response;
}, error => {
console.log('catch', error)
if (error.response) {
switch (error.response.status) {
case 401:
sessionStorage.removeItem('user_token') //可能是token过期清除它
router.replace({ //跳转到登录页面
path: '/',
query: { redirect: router.currentRoute.fullPath } // 将跳转的路由path作为参数登录成功后跳转到该路由
})
break;
case 404:
store.commit('setServiceError', true);
break;
case 500:
break;
}
} else {
store.commit('setServiceError', true);
}
return Promise.reject(error)
})
//按照请求类型对axios进行封装
const api = {
get(url, data) {
return instance.get(url, { params: data })
},
post(url, data) {
let newData = (url.indexOf("install") > 0 || url.indexOf("sys") > 0) ? JSON.stringify(data) : qs.stringify(data)
if (url.indexOf("install") > 0) {
axios.defaults.headers.post['Content-Type'] = 'application/json';
} else {
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8';
}
return instance.post(url, newData)
},
put(url, data) {
let newData = (url.indexOf("setting") > 0) ? JSON.stringify(data) : qs.stringify(data)
if (url.indexOf("setting") > 0) {
axios.defaults.headers.post['Content-Type'] = 'application/json';
} else {
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8';
}
return instance.put(url, newData)
},
delete(url, data) {
return instance.delete(url, { params: data })
}
}
export { api }

View file

@ -1,21 +0,0 @@
/*
* @Author: JerryK
* @Date: 2021-09-18 21:32:13
* @LastEditors: JerryK
* @LastEditTime: 2021-09-19 09:26:45
* @Description: Task API
* @FilePath: \CasaOS-UI\src\service\task.js
*/
import { api } from "./service.js";
const task = {
//List
list() {
return api.get("/task/list");
},
//Mark
completion(id) {
return api.put(`/task/completion/${id}`);
}
}
export default task;

View file

@ -1,47 +0,0 @@
/*
* @Author: JerryK
* @Date: 2021-09-18 21:32:13
* @LastEditors: JerryK
* @LastEditTime: 2021-09-19 09:26:47
* @Description: User API
* @FilePath: \CasaOS-UI\src\service\user.js
*/
import { api } from "./service.js";
const user = {
//login
login(data) {
return api.post("user/login", data);
},
// Create UserName and Password
createUsernameAndPaword(data) {
return api.post("/user/setusernamepwd", data);
},
// Change User Avatar
changeAvatar(data) {
return api.post("/user/changhead", data);
},
// Change UserName
changeUserName(data) {
return api.put("/user/changusername", data);
},
// Change User Password
changePassword(data) {
return api.put("/user/changuserpwd", data);
},
// Get user info
getUserInfo() {
return api.get("/user/info");
},
// Change User Info
changeUserInfo(data) {
return api.post('/user/changuserinfo', data)
}
}
export default user;

View file

@ -1,64 +0,0 @@
/*
* @Author: JerryK
* @Date: 2021-09-18 21:32:13
* @LastEditors: JerryK
* @LastEditTime: 2021-09-19 09:26:50
* @Description: Zerotier API
* @FilePath: \CasaOS-UI\src\service\zerotier.js
*/
import { api } from "./service.js";
const zerotier = {
//Check if Need login to zerotier
isLogin() {
return api.get("/zerotier/islogin");
},
//Login
login(data) {
return api.post("/zerotier/login", data);
},
//Register
register(data) {
return api.post('/zerotier/register', data);
},
//networklist
networkLits() {
return api.get('/zerotier/list');
},
//joinNetwork
joinNetwork(id) {
return api.post(`/zerotier/join/${id}`);
},
// leaveNetwork
leaveNetwork(id) {
return api.post(`/zerotier/leave/${id}`);
},
// Get Network detial
networkDetail(id) {
return api.get(`/zerotier/info/${id}`);
},
// Edit Network
editNetwork(id, data) {
return api.put(`/zerotier/edit/${id}`, data)
},
// Delete A Network
delNetwork(id) {
return api.delete(`/zerotier/network/${id}/del`)
},
createNetwork() {
return api.post('/zerotier/create')
},
// Get Network member list
getMembers(id) {
return api.get(`/zerotier/member/${id}`)
},
// Edit Member
editMember(id, mId, data) {
return api.put(`/zerotier/member/${id}/edit/${mId}`, data)
},
// Delete Member
delMemeber(id, mId) {
return api.delete(`/zerotier/member/${id}/del/${mId}`)
}
}
export default zerotier;

View file

@ -1,34 +0,0 @@
/*
* @Author: JerryK
* @Date: 2021-09-18 21:32:13
* @LastEditors: JerryK
* @LastEditTime: 2021-09-22 16:28:16
* @Description:
* @FilePath: /CasaOS-UI/src/store/index.js
*/
import Vue from 'vue'
import Vuex from 'vuex'
//import createPersistedState from "vuex-persistedstate";
Vue.use(Vuex)
export default new Vuex.Store({
//plugins: [createPersistedState()],
state: {
token: "",
devIp: "192.168.2.217",
serviceError: false
},
mutations: {
setToken(state, val) {
state.token = val
},
setServiceError(state, val) {
state.serviceError = val
}
},
actions: {
},
modules: {
}
})

View file

@ -1,23 +0,0 @@
/*
* @Author: JerryK
* @Date: 2021-09-22 10:10:10
* @LastEditors: JerryK
* @LastEditTime: 2021-09-22 15:26:47
* @Description:
* @FilePath: /CasaOS-UI/vue.config.js
*/
const webpack = require('webpack')
module.exports = {
publicPath: '/ui/',
runtimeCompiler: true,
lintOnSave: false,
productionSourceMap: false,
pluginOptions: {
},
chainWebpack: config => {
config.plugin('ignore')
.use(new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/));
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,8 @@
[app] [app]
PAGE_SIZE = 10 PAGE_SIZE = 10
RuntimeRootPath = runtime/ RuntimeRootPath = runtime/
LogSavePath = /casaOS/logs/server/ ;LogSavePath = /casaOS/logs/server/
LogSavePath = /oasis/logs/server/
LogSaveName = log LogSaveName = log
LogFileExt = log LogFileExt = log
; 必须的格式 ; 必须的格式
@ -9,6 +10,7 @@ DateStrFormat = 20060102
DateTimeFormat = 2006-01-02 15:04:05 DateTimeFormat = 2006-01-02 15:04:05
TimeFormat = 15:04:05 TimeFormat = 15:04:05
DateFormat = 2006-01-02 DateFormat = 2006-01-02
ProjectPath = /casaOS/server
[server] [server]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 116 KiB

3
go.mod
View file

@ -1,4 +1,4 @@
module oasis module github.com/IceWhaleTech/CasaOS
go 1.16 go 1.16
@ -50,7 +50,6 @@ require (
golang.org/x/tools v0.1.3 // indirect golang.org/x/tools v0.1.3 // indirect
google.golang.org/grpc v1.39.0 // indirect google.golang.org/grpc v1.39.0 // indirect
gopkg.in/ini.v1 v1.62.0 // indirect gopkg.in/ini.v1 v1.62.0 // indirect
gorm.io/driver/mysql v1.1.1 // indirect
gorm.io/driver/sqlite v1.1.5 gorm.io/driver/sqlite v1.1.5
gorm.io/gorm v1.21.15 gorm.io/gorm v1.21.15
src.techknowlogick.com/xgo v1.4.1-0.20210909190026-ce016894db20 // indirect src.techknowlogick.com/xgo v1.4.1-0.20210909190026-ce016894db20 // indirect

10
main.go
View file

@ -3,15 +3,15 @@ package main
import ( import (
"flag" "flag"
"fmt" "fmt"
"github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/pkg/sqlite"
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
"github.com/IceWhaleTech/CasaOS/route"
"github.com/IceWhaleTech/CasaOS/service"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/robfig/cron" "github.com/robfig/cron"
"gorm.io/gorm" "gorm.io/gorm"
"net/http" "net/http"
"oasis/pkg/config"
"oasis/pkg/sqlite"
loger2 "oasis/pkg/utils/loger"
"oasis/route"
"oasis/service"
"time" "time"
) )

View file

@ -2,9 +2,9 @@ package config
import ( import (
"fmt" "fmt"
"github.com/IceWhaleTech/CasaOS/model"
"github.com/go-ini/ini" "github.com/go-ini/ini"
"log" "log"
"oasis/model"
"os" "os"
"path" "path"
"path/filepath" "path/filepath"
@ -55,7 +55,8 @@ func InitSetup(config string) {
mapTo("redis", RedisInfo) mapTo("redis", RedisInfo)
mapTo("server", ServerInfo) mapTo("server", ServerInfo)
mapTo("system", SystemConfigInfo) mapTo("system", SystemConfigInfo)
AppInfo.ProjectPath = getCurrentDirectory() //os.Getwd() // AppInfo.ProjectPath = getCurrentDirectory() //os.Getwd()
} }
//映射 //映射

View file

@ -2,10 +2,10 @@ package sqlite
import ( import (
"fmt" "fmt"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
model2 "github.com/IceWhaleTech/CasaOS/service/model"
"gorm.io/driver/sqlite" "gorm.io/driver/sqlite"
"gorm.io/gorm" "gorm.io/gorm"
"oasis/pkg/utils/file"
model2 "oasis/service/model"
"time" "time"
) )

View file

@ -1,9 +1,9 @@
package upnp package upnp
import ( import (
ip_helper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/ip_helper"
"github.com/pkg/errors" "github.com/pkg/errors"
"net" "net"
ip_helper2 "oasis/pkg/utils/ip_helper"
"strings" "strings"
) )

View file

@ -3,11 +3,11 @@ package httper
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/tidwall/gjson" "github.com/tidwall/gjson"
"io" "io"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"oasis/pkg/config"
"time" "time"
) )

View file

@ -1,8 +1,8 @@
package ip_helper package ip_helper
import ( import (
httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
"net" "net"
httper2 "oasis/pkg/utils/httper"
"strings" "strings"
) )

View file

@ -2,11 +2,11 @@ package jwt
import ( import (
"fmt" "fmt"
"github.com/IceWhaleTech/CasaOS/model"
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"net/http" "net/http"
"oasis/model"
loger2 "oasis/pkg/utils/loger"
oasis_err2 "oasis/pkg/utils/oasis_err"
"time" "time"
) )

View file

@ -2,9 +2,9 @@ package loger
import ( import (
"fmt" "fmt"
"github.com/IceWhaleTech/CasaOS/pkg/config"
file2 "github.com/IceWhaleTech/CasaOS/pkg/utils/file"
"log" "log"
"oasis/pkg/config"
file2 "oasis/pkg/utils/file"
"os" "os"
"path/filepath" "path/filepath"
"runtime" "runtime"

View file

@ -1,7 +1,7 @@
package sort package sort
import ( import (
"oasis/model" "github.com/IceWhaleTech/CasaOS/model"
"sort" "sort"
) )

View file

@ -1,7 +1,7 @@
package sort package sort
import ( import (
"oasis/model" "github.com/IceWhaleTech/CasaOS/model"
"sort" "sort"
) )

View file

@ -1,7 +1,7 @@
package sort package sort
import ( import (
"oasis/model" "github.com/IceWhaleTech/CasaOS/model"
"sort" "sort"
) )

View file

@ -1,7 +1,7 @@
package sort package sort
import ( import (
"oasis/model" "github.com/IceWhaleTech/CasaOS/model"
"sort" "sort"
) )

View file

@ -2,11 +2,11 @@ package version
import ( import (
json2 "encoding/json" json2 "encoding/json"
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
"github.com/IceWhaleTech/CasaOS/types"
"github.com/tidwall/gjson" "github.com/tidwall/gjson"
"oasis/model"
"oasis/pkg/config"
"oasis/pkg/utils/httper"
"oasis/types"
"strconv" "strconv"
"strings" "strings"
) )

View file

@ -1,14 +1,13 @@
package zerotier package zerotier
import ( import (
httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
"github.com/tidwall/gjson" "github.com/tidwall/gjson"
"net/http" "net/http"
httper2 "oasis/pkg/utils/httper"
) )
func PostData(url, token string, data string) interface{} { func PostData(url, token string, data string) interface{} {
body, code := httper2.ZeroTierPostJson(url, data, GetHead(token)) body, code := httper2.ZeroTierPostJson(url, data, GetHead(token))
if code != http.StatusOK { if code != http.StatusOK {

View file

@ -3,9 +3,9 @@
package route package route
import ( import (
_ "github.com/IceWhaleTech/CasaOS/docs"
ginSwagger "github.com/swaggo/gin-swagger" ginSwagger "github.com/swaggo/gin-swagger"
"github.com/swaggo/gin-swagger/swaggerFiles" "github.com/swaggo/gin-swagger/swaggerFiles"
_ "oasis/docs"
) )
func init() { func init() {

View file

@ -1,13 +1,13 @@
package route package route
import ( import (
"github.com/IceWhaleTech/CasaOS/middleware"
"github.com/IceWhaleTech/CasaOS/pkg/config"
jwt2 "github.com/IceWhaleTech/CasaOS/pkg/utils/jwt"
v1 "github.com/IceWhaleTech/CasaOS/route/v1"
"github.com/IceWhaleTech/CasaOS/web"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"net/http" "net/http"
"oasis/middleware"
"oasis/pkg/config"
jwt2 "oasis/pkg/utils/jwt"
v1 "oasis/route/v1"
"oasis/web"
) )
var swagHandler gin.HandlerFunc var swagHandler gin.HandlerFunc
@ -19,9 +19,10 @@ func InitRouter(swagHandler gin.HandlerFunc) *gin.Engine {
gin.SetMode(config.ServerInfo.RunMode) gin.SetMode(config.ServerInfo.RunMode)
r.StaticFS("/ui", http.FS(web.Static)) r.StaticFS("/ui", http.FS(web.Static))
r.GET("/", func(c *gin.Context) { r.GET("/", WebUIHome)
c.Redirect(http.StatusMovedPermanently, "ui/") //r.GET("/", func(c *gin.Context) {
}) // c.Redirect(http.StatusMovedPermanently, "ui/")
//})
if swagHandler != nil { if swagHandler != nil {
r.GET("/swagger/*any", swagHandler) r.GET("/swagger/*any", swagHandler)
} }

14
route/ui.go Normal file
View file

@ -0,0 +1,14 @@
package route
import (
"github.com/IceWhaleTech/CasaOS/web"
"github.com/gin-gonic/gin"
"html/template"
)
func WebUIHome(c *gin.Context) {
c.Writer.Header().Set("Content-Type", "text/html; charset=utf-8")
index, _ := template.ParseFS(web.Static, "index.html")
index.Execute(c.Writer, nil)
return
}

View file

@ -1,14 +1,14 @@
package v1 package v1
import ( import (
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
port2 "github.com/IceWhaleTech/CasaOS/pkg/utils/port"
"github.com/IceWhaleTech/CasaOS/pkg/utils/sort"
"github.com/IceWhaleTech/CasaOS/service"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"net/http" "net/http"
"oasis/model"
"oasis/pkg/utils/file"
oasis_err2 "oasis/pkg/utils/oasis_err"
port2 "oasis/pkg/utils/port"
"oasis/pkg/utils/sort"
"oasis/service"
"strconv" "strconv"
) )

View file

@ -2,14 +2,14 @@ package v1
import ( import (
"fmt" "fmt"
"github.com/IceWhaleTech/CasaOS/model"
ip_helper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/ip_helper"
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
"github.com/IceWhaleTech/CasaOS/service"
model2 "github.com/IceWhaleTech/CasaOS/service/model"
"github.com/forease/gotld" "github.com/forease/gotld"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"net/http" "net/http"
"oasis/model"
ip_helper2 "oasis/pkg/utils/ip_helper"
oasis_err2 "oasis/pkg/utils/oasis_err"
"oasis/service"
model2 "oasis/service/model"
"os/exec" "os/exec"
"strconv" "strconv"
"strings" "strings"

View file

@ -1,12 +1,12 @@
package v1 package v1
import ( import (
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
"github.com/IceWhaleTech/CasaOS/service"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/shirou/gopsutil/v3/disk" "github.com/shirou/gopsutil/v3/disk"
"net/http" "net/http"
"oasis/model"
"oasis/pkg/utils/oasis_err"
"oasis/service"
"strconv" "strconv"
) )

View file

@ -3,23 +3,23 @@ package v1
import ( import (
"bytes" "bytes"
json2 "encoding/json" json2 "encoding/json"
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/docker"
upnp2 "github.com/IceWhaleTech/CasaOS/pkg/upnp"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
ip_helper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/ip_helper"
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
port2 "github.com/IceWhaleTech/CasaOS/pkg/utils/port"
"github.com/IceWhaleTech/CasaOS/pkg/utils/random"
"github.com/IceWhaleTech/CasaOS/service"
"github.com/IceWhaleTech/CasaOS/service/docker_base"
model2 "github.com/IceWhaleTech/CasaOS/service/model"
"github.com/IceWhaleTech/CasaOS/types"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
"github.com/jinzhu/copier" "github.com/jinzhu/copier"
uuid "github.com/satori/go.uuid" uuid "github.com/satori/go.uuid"
"net/http" "net/http"
"oasis/model"
"oasis/pkg/docker"
upnp2 "oasis/pkg/upnp"
"oasis/pkg/utils/file"
ip_helper2 "oasis/pkg/utils/ip_helper"
oasis_err2 "oasis/pkg/utils/oasis_err"
port2 "oasis/pkg/utils/port"
"oasis/pkg/utils/random"
"oasis/service"
"oasis/service/docker_base"
model2 "oasis/service/model"
"oasis/types"
"reflect" "reflect"
"strconv" "strconv"
"strings" "strings"

View file

@ -4,14 +4,14 @@ import (
"bufio" "bufio"
"encoding/csv" "encoding/csv"
"fmt" "fmt"
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
"github.com/IceWhaleTech/CasaOS/service"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"io" "io"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"oasis/model"
"oasis/pkg/utils/file"
oasis_err2 "oasis/pkg/utils/oasis_err"
"oasis/service"
"os" "os"
"path" "path"
) )

View file

@ -2,13 +2,13 @@ package v1
import ( import (
json2 "encoding/json" json2 "encoding/json"
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
"github.com/IceWhaleTech/CasaOS/service"
"github.com/IceWhaleTech/CasaOS/types"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
"net/http" "net/http"
"oasis/model"
"oasis/pkg/utils/oasis_err"
"oasis/service"
"oasis/types"
"time" "time"
) )

View file

@ -1,12 +1,12 @@
package v1 package v1
import ( import (
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
"github.com/IceWhaleTech/CasaOS/service"
model2 "github.com/IceWhaleTech/CasaOS/service/model"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"net/http" "net/http"
"oasis/model"
"oasis/pkg/utils/oasis_err"
"oasis/service"
model2 "oasis/service/model"
"strconv" "strconv"
) )

View file

@ -1,13 +1,13 @@
package v1 package v1
import ( import (
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
"github.com/IceWhaleTech/CasaOS/service"
model2 "github.com/IceWhaleTech/CasaOS/service/model"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"net/http" "net/http"
"net/url" "net/url"
"oasis/model"
"oasis/pkg/utils/oasis_err"
"oasis/service"
model2 "oasis/service/model"
) )
// @Summary 获取短链列表 // @Summary 获取短链列表

View file

@ -2,15 +2,15 @@ package v1
import ( import (
"fmt" "fmt"
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
"github.com/IceWhaleTech/CasaOS/pkg/utils/version"
"github.com/IceWhaleTech/CasaOS/service"
model2 "github.com/IceWhaleTech/CasaOS/service/model"
"github.com/IceWhaleTech/CasaOS/types"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"net/http" "net/http"
"oasis/model"
"oasis/pkg/config"
"oasis/pkg/utils/oasis_err"
"oasis/pkg/utils/version"
"oasis/service"
model2 "oasis/service/model"
"oasis/types"
"strconv" "strconv"
"time" "time"
) )
@ -51,8 +51,10 @@ func CheckVersion(c *gin.Context) {
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /sys/update [post] // @Router /sys/update [post]
func SystemUpdate(c *gin.Context) { func SystemUpdate(c *gin.Context) {
fmt.Println("开始更新")
need, version := version.IsNeedUpdate() need, version := version.IsNeedUpdate()
if need { if need {
fmt.Println("进入更新")
service.MyService.System().UpdateSystemVersion(version.Version) service.MyService.System().UpdateSystemVersion(version.Version)
} }
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)}) c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})

View file

@ -1,13 +1,13 @@
package v1 package v1
import ( import (
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
"github.com/IceWhaleTech/CasaOS/service"
model2 "github.com/IceWhaleTech/CasaOS/service/model"
"github.com/IceWhaleTech/CasaOS/types"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"net/http" "net/http"
"oasis/model"
"oasis/pkg/utils/oasis_err"
"oasis/service"
model2 "oasis/service/model"
"oasis/types"
"strconv" "strconv"
) )

View file

@ -2,13 +2,13 @@ package v1
import ( import (
"fmt" "fmt"
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/config"
jwt2 "github.com/IceWhaleTech/CasaOS/pkg/utils/jwt"
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
"github.com/IceWhaleTech/CasaOS/service"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"net/http" "net/http"
"oasis/model"
"oasis/pkg/config"
jwt2 "oasis/pkg/utils/jwt"
oasis_err2 "oasis/pkg/utils/oasis_err"
"oasis/service"
) )
var user_service service.UserService var user_service service.UserService

View file

@ -2,12 +2,12 @@ package v1
import ( import (
json2 "encoding/json" json2 "encoding/json"
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/config"
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
"github.com/IceWhaleTech/CasaOS/service"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"net/http" "net/http"
"oasis/model"
"oasis/pkg/config"
oasis_err2 "oasis/pkg/utils/oasis_err"
"oasis/service"
) )
// @Summary 登录zerotier获取token // @Summary 登录zerotier获取token

View file

@ -1,12 +1,12 @@
package v1 package v1
import ( import (
"github.com/IceWhaleTech/CasaOS/model"
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
"github.com/IceWhaleTech/CasaOS/service"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/shirou/gopsutil/v3/disk" "github.com/shirou/gopsutil/v3/disk"
"net/http" "net/http"
"oasis/model"
oasis_err2 "oasis/pkg/utils/oasis_err"
"oasis/service"
"strings" "strings"
"time" "time"
"unsafe" "unsafe"

View file

@ -3,19 +3,19 @@ package service
import ( import (
"context" "context"
json2 "encoding/json" json2 "encoding/json"
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/pkg/docker"
"github.com/IceWhaleTech/CasaOS/pkg/utils/command"
httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
model2 "github.com/IceWhaleTech/CasaOS/service/model"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/filters"
client2 "github.com/docker/docker/client" client2 "github.com/docker/docker/client"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/tidwall/gjson" "github.com/tidwall/gjson"
"gorm.io/gorm" "gorm.io/gorm"
"oasis/model"
"oasis/pkg/config"
"oasis/pkg/docker"
"oasis/pkg/utils/command"
httper2 "oasis/pkg/utils/httper"
loger2 "oasis/pkg/utils/loger"
model2 "oasis/service/model"
"strings" "strings"
"time" "time"
) )

View file

@ -1,11 +1,11 @@
package service package service
import ( import (
ip_helper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/ip_helper"
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
"github.com/IceWhaleTech/CasaOS/service/ddns"
"github.com/IceWhaleTech/CasaOS/service/model"
"gorm.io/gorm" "gorm.io/gorm"
ip_helper2 "oasis/pkg/utils/ip_helper"
loger2 "oasis/pkg/utils/loger"
"oasis/service/ddns"
"oasis/service/model"
"os/exec" "os/exec"
) )

View file

@ -4,10 +4,10 @@ import (
"bytes" "bytes"
"context" "context"
"fmt" "fmt"
"github.com/IceWhaleTech/CasaOS/pkg/ddns"
"github.com/tidwall/gjson" "github.com/tidwall/gjson"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"oasis/pkg/ddns"
"time" "time"
) )

View file

@ -3,12 +3,12 @@ package service
import ( import (
json2 "encoding/json" json2 "encoding/json"
"fmt" "fmt"
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/config"
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
"github.com/shirou/gopsutil/v3/disk" "github.com/shirou/gopsutil/v3/disk"
"github.com/tidwall/gjson" "github.com/tidwall/gjson"
"oasis/model"
"oasis/pkg/config"
command2 "oasis/pkg/utils/command"
loger2 "oasis/pkg/utils/loger"
"strconv" "strconv"
"strings" "strings"
) )

View file

@ -7,14 +7,19 @@ import (
"encoding/binary" "encoding/binary"
json2 "encoding/json" json2 "encoding/json"
"fmt" "fmt"
model2 "github.com/IceWhaleTech/CasaOS/service/model"
types2 "github.com/IceWhaleTech/CasaOS/types"
"github.com/containerd/containerd" "github.com/containerd/containerd"
"github.com/containerd/containerd/cio" "github.com/containerd/containerd/cio"
"github.com/containerd/containerd/namespaces" "github.com/containerd/containerd/namespaces"
"github.com/containerd/containerd/oci" "github.com/containerd/containerd/oci"
model2 "oasis/service/model"
types2 "oasis/types"
"syscall" "syscall"
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/docker"
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
//"github.com/containerd/containerd/oci" //"github.com/containerd/containerd/oci"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/container"
@ -26,11 +31,6 @@ import (
"io" "io"
"io/ioutil" "io/ioutil"
"log" "log"
"oasis/model"
"oasis/pkg/docker"
command2 "oasis/pkg/utils/command"
"oasis/pkg/utils/file"
loger2 "oasis/pkg/utils/loger"
"os" "os"
"strconv" "strconv"
"strings" "strings"

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