Compare commits

..

No commits in common. "master" and "v0.0.1" have entirely different histories.

8 changed files with 49 additions and 222 deletions

View File

@ -1,11 +0,0 @@
GOPATH:=$(shell go env GOPATH)
DATETIME:=$(shell date "+%Y-%m-%d %H:%M:%S")
PKGNAME:="git.nobla.cn/golang/moto"
GIT_VERSION=$(shell git rev-parse --short HEAD)
.PHONY: build
build:
go mod tidy
go mod vendor
CGO_ENABLED=0 go build -a -installsuffix cgo -ldflags "-s -w -X '$(PKGNAME)/version.Version=$(GIT_VERSION)' -X '$(PKGNAME)/version.BuildDate=$(DATETIME)'" -o ./bin/$(APP_NAME) ./cmd/main.go

View File

@ -10,4 +10,4 @@ adminUsers:
system: system:
settings: settings:
productName: "测试网址" productName: "测试网址"
copyright: "版权所有,防盗必究" copyright: "xxx"

View File

@ -1,192 +0,0 @@
package main
import (
"archive/tar"
"bytes"
"compress/gzip"
"errors"
"flag"
"fmt"
"git.nobla.cn/golang/kos/util/env"
"io"
"net/http"
"os"
"path"
"runtime"
"strconv"
"strings"
"time"
)
var (
packageNameFlag = flag.String("package-name", "", "应用程序包名称")
versionFlag = flag.String("version", env.Get("MOTO_VERSION", "v0.0.3"), "模板版本号,可以使用环境变量 MOTO_VERSION")
)
var (
oldPackageName = "git.nobla.cn/golang/moto"
)
func writeFile(dstFile string, r io.Reader) (err error) {
var (
fp *os.File
)
if fp, err = os.Create(dstFile); err != nil {
return
}
defer fp.Close()
_, err = io.Copy(fp, r)
return
}
func extractFile(file string, dirname string) (err error) {
var (
prefix string
fp *os.File
gzipReader *gzip.Reader
)
// 清理路径字符串
dirname = path.Clean(dirname)
// 打开压缩文件
if fp, err = os.Open(file); err != nil {
return
}
defer fp.Close()
// 执行解压操作
if gzipReader, err = gzip.NewReader(fp); err != nil {
return
}
defer gzipReader.Close()
tarReader := tar.NewReader(gzipReader)
for {
header, errRead := tarReader.Next()
if errRead != nil {
if errors.Is(errRead, io.EOF) {
break
}
err = errRead
break
}
if header.Typeflag == tar.TypeXGlobalHeader {
continue
}
if prefix == "" && header.Typeflag == tar.TypeDir {
prefix = header.Name
continue
}
realname := strings.TrimPrefix(header.Name, prefix)
if strings.HasPrefix(realname, "generator") {
continue
}
filename := path.Join(dirname, realname)
if header.Typeflag == tar.TypeDir {
if err = os.MkdirAll(filename, 0755); err != nil {
return
}
} else {
if err = writeFile(filename, tarReader); err != nil {
return err
}
if runtime.GOOS != "windows" {
os.Chmod(filename, 0644)
}
}
}
return nil
}
func downloadPackage(version string, dirname string) (err error) {
var (
uri string
res *http.Response
)
uri = "https://git.nobla.cn/golang/moto/archive/" + version + ".tar.gz"
if res, err = http.Get(uri); err != nil {
return
}
defer func() {
res.Body.Close()
}()
if res.StatusCode != http.StatusOK {
err = errors.New(res.Status)
return
}
filename := path.Join(os.TempDir(), strconv.FormatInt(time.Now().UnixMilli(), 10)+".tar.gz")
if err = writeFile(filename, res.Body); err != nil {
return
}
err = extractFile(filename, dirname)
return
}
func replaceFiles(dirname string, source, replace string) (err error) {
var (
buf []byte
files []os.DirEntry
)
if files, err = os.ReadDir(dirname); err != nil {
if errors.Is(err, io.EOF) {
return nil
}
return err
}
sb := []byte(source)
rb := []byte(replace)
for _, file := range files {
if file.Name() == "." || file.Name() == ".." {
continue
}
filename := path.Join(dirname, file.Name())
if file.IsDir() {
err = replaceFiles(filename, source, replace)
} else {
if buf, err = os.ReadFile(filename); err == nil {
buf = bytes.ReplaceAll(buf, sb, rb)
os.WriteFile(filename, buf, 064)
}
}
}
return
}
func main() {
var (
pos int
err error
dirname string
appname string
packageName string
)
flag.Parse()
packageName = *packageNameFlag
if packageName == "" {
if len(os.Args) > 1 {
packageName = os.Args[1]
}
}
pos = strings.LastIndexByte(packageName, '/')
if pos == -1 {
fmt.Println("应用包名称是无效的")
os.Exit(1)
}
appname = packageName[pos:]
if dirname, err = os.Getwd(); err != nil {
fmt.Println("获取应用目录失败:" + err.Error())
os.Exit(1)
}
dirname = path.Join(dirname, appname)
if err = os.MkdirAll(dirname, 0755); err != nil {
fmt.Println("创建应用目录失败:" + err.Error())
os.Exit(1)
}
if err = downloadPackage(*versionFlag, dirname); err != nil {
fmt.Println("下载模板文件失败:" + err.Error())
os.Exit(1)
}
if err = replaceFiles(dirname, oldPackageName, packageName); err != nil {
fmt.Println("生产应用文件失败:" + err.Error())
os.Exit(1)
}
fmt.Println("创建项目成功")
}

View File

@ -60,11 +60,6 @@
} }
} }
.el-select {
--el-border-color: var(--form-control-border-color);
}
.el-input { .el-input {
--el-input-border-color: var(--form-control-border-color); --el-input-border-color: var(--form-control-border-color);

View File

@ -28,9 +28,12 @@
<div class="header-avatar"> <div class="header-avatar">
<el-avatar :size="36" :title="username" :src="avatar"> <el-avatar :size="36" :title="username" :src="avatar">
</el-avatar> </el-avatar>
<i class="user-status" :style="{ backgroundColor: userStateColor }" :title="userStateText"
@click="dialogVisible = true"></i>
</div> </div>
<template #dropdown> <template #dropdown>
<el-dropdown-menu> <el-dropdown-menu>
<el-dropdown-item command="status">设置状态</el-dropdown-item>
<el-dropdown-item command="profile">个人设置</el-dropdown-item> <el-dropdown-item command="profile">个人设置</el-dropdown-item>
<el-dropdown-item divided command="logout">退出系统</el-dropdown-item> <el-dropdown-item divided command="logout">退出系统</el-dropdown-item>
</el-dropdown-menu> </el-dropdown-menu>
@ -40,10 +43,28 @@
</ul> </ul>
</div> </div>
</div> </div>
<el-dialog class="status-dialog" v-model="dialogVisible" width="320px" draggable>
<div class="current-status">
<div>
<i :style="{ backgroundColor: userStateColor }"></i> <span>{{ userStateText }}</span>
</div>
</div>
<el-row :gutter="10">
<el-col :span="8" v-for="item in userStatus">
<div class="status-item" @click="handleSetStatus(item)"
:class="item.value === userState ? 'active' : ''">
<div class="status-avatar">
<i :style="{ backgroundColor: item.color }"></i>
</div>
<div class="status-text">{{ item.label }}</div>
</div>
</el-col>
</el-row>
</el-dialog>
</template> </template>
<script setup> <script setup>
import { inject, onMounted, onUnmounted } from 'vue'; import { computed, h, inject, onMounted, onUnmounted, ref } from 'vue';
import useSystemStore from '@/stores/system' import useSystemStore from '@/stores/system'
import useThemeStore from '@/stores/theme' import useThemeStore from '@/stores/theme'
import useUserStore from '@/stores/user' import useUserStore from '@/stores/user'
@ -51,11 +72,15 @@ import { storeToRefs } from 'pinia';
import screenfull from 'screenfull'; import screenfull from 'screenfull';
import Icon from '@/components/widgets/Icon.vue'; import Icon from '@/components/widgets/Icon.vue';
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { getUserStatus, getStatusText, getStatusTextColor } from '@/assets/js/status'
import { ElNotification } from 'element-plus';
const systemStore = useSystemStore(); const systemStore = useSystemStore();
const themeStore = useThemeStore(); const themeStore = useThemeStore();
const userStore = useUserStore(); const userStore = useUserStore();
const userState = ref('idle');
const dialogVisible = ref(false);
const { logoUrl, productName } = storeToRefs(systemStore); const { logoUrl, productName } = storeToRefs(systemStore);
const { headerBackgroundColor } = storeToRefs(themeStore); const { headerBackgroundColor } = storeToRefs(themeStore);
@ -66,6 +91,17 @@ const logout = inject('logout');
const router = useRouter() const router = useRouter()
const userStatus = computed(() => {
return getUserStatus();
})
const userStateText = computed(() => {
return getStatusText(userState.value)
})
const userStateColor = computed(() => {
return getStatusTextColor(userState.value)
})
const handleFullscreen = (e) => { const handleFullscreen = (e) => {
if (screenfull.isEnabled) { if (screenfull.isEnabled) {
@ -81,8 +117,15 @@ const handleToggleMenuVisible = (e) => {
systemStore.toggleFlowSidebarVisible() systemStore.toggleFlowSidebarVisible()
} }
const handleSetStatus = (e) => {
}
const handleMenuCommand = (e) => { const handleMenuCommand = (e) => {
switch (e) { switch (e) {
case 'status':
dialogVisible.value = true;
break;
case 'profile': case 'profile':
router.push('/organize/user/profile') router.push('/organize/user/profile')
break break

View File

@ -40,6 +40,8 @@ import { storeToRefs } from 'pinia';
import useThemeStore from '@/stores/theme' import useThemeStore from '@/stores/theme'
import useSystemStore from '@/stores/system' import useSystemStore from '@/stores/system'
import useUserStore from '@/stores/user' import useUserStore from '@/stores/user'
import { getBaseHost } from '@/apis/request'
import { updateStatusMap } from '@/assets/js/status'
import { userLogout, getUserProfile } from '@/apis/organize' import { userLogout, getUserProfile } from '@/apis/organize'
import { getConfigure } from '@/apis/system' import { getConfigure } from '@/apis/system'

View File

@ -2,19 +2,9 @@
<div class="d-flex align-center"> <div class="d-flex align-center">
<div class="flex-shrink"> <div class="flex-shrink">
</div> </div>
<div class="flex-fill"> <div class="flex-fill"></div>
<div class="text-right text-muted">{{ copyright }}</div>
</div>
</div> </div>
</template> </template>
<script setup> <script setup>
import useSystemStore from '@/stores/system'
import { storeToRefs } from 'pinia';
const systemStore = useSystemStore()
const { copyright } = storeToRefs(systemStore);
</script> </script>

View File

@ -10,7 +10,7 @@ const useSystemStore = defineStore('system', {
lang: 'zh-CN', lang: 'zh-CN',
logoUrl: '//s3.tebi.io/tenos/images/logo/jc.png', logoUrl: '//s3.tebi.io/tenos/images/logo/jc.png',
copyright: '2005-2023 JUSTCALL 版权 © 2023 集时股份呼叫中心开发团队', copyright: '2005-2023 JUSTCALL 版权 © 2023 集时股份呼叫中心开发团队',
productName: '管理系统', productName: '在线系统',
variables: {}, variables: {},
} }
}, },