mirror of https://gitee.com/godoos/godoos.git
21 changed files with 1078 additions and 66 deletions
@ -0,0 +1,157 @@ |
|||
<script setup lang="ts"> |
|||
import { Plus } from '@element-plus/icons-vue' |
|||
import { ref, computed } from "vue"; |
|||
import { OpenDirDialog } from "@/util/goutil"; |
|||
interface ProxyItem { |
|||
id: number; |
|||
dir: string; |
|||
username: string; |
|||
password: string; |
|||
} |
|||
const localKey = "godoos_local_nas" |
|||
const getProxies = (): ProxyItem[] => { |
|||
const proxies = localStorage.getItem(localKey); |
|||
return proxies ? JSON.parse(proxies) : []; |
|||
}; |
|||
|
|||
const saveProxies = (proxies: ProxyItem[]) => { |
|||
localStorage.setItem(localKey, JSON.stringify(proxies)); |
|||
}; |
|||
|
|||
const proxies = ref<ProxyItem[]>(getProxies()); |
|||
const initData = { |
|||
id: Date.now(), |
|||
dir: "", |
|||
username: "", |
|||
password: "", |
|||
} |
|||
const proxyData = ref<ProxyItem>(initData); |
|||
const proxyDialogShow = ref(false); |
|||
const isEditing = ref(false); |
|||
const pwdRef = ref<any>(null); |
|||
|
|||
const addProxy = () => { |
|||
if (pwdRef.value.validate()) { |
|||
proxies.value.push({ ...proxyData.value }); |
|||
saveProxies(proxies.value); |
|||
proxyDialogShow.value = false; |
|||
proxyData.value = initData; |
|||
} |
|||
}; |
|||
|
|||
const editNas = (proxy: ProxyItem) => { |
|||
proxyData.value = { ...proxy }; |
|||
isEditing.value = true; |
|||
proxyDialogShow.value = true; |
|||
}; |
|||
|
|||
const updateProxy = () => { |
|||
if (pwdRef.value.validate()) { |
|||
const index = proxies.value.findIndex(p => p.id === proxyData.value.id); |
|||
if (index !== -1) { |
|||
proxies.value[index] = { ...proxyData.value }; |
|||
saveProxies(proxies.value); |
|||
proxyDialogShow.value = false; |
|||
proxyData.value = initData; |
|||
isEditing.value = false; |
|||
} |
|||
} |
|||
}; |
|||
function selectFile() { |
|||
OpenDirDialog().then((res: string) => { |
|||
proxyData.value.dir = res; |
|||
}); |
|||
} |
|||
const deleteNas = (id: number) => { |
|||
proxies.value = proxies.value.filter(p => p.id !== id); |
|||
saveProxies(proxies.value); |
|||
}; |
|||
|
|||
const saveNas = () => { |
|||
pwdRef.value.validate((valid: boolean) => { |
|||
if (valid) { |
|||
if (isEditing.value) { |
|||
updateProxy(); |
|||
} else { |
|||
addProxy(); |
|||
} |
|||
} else { |
|||
console.log('表单验证失败'); |
|||
} |
|||
}); |
|||
}; |
|||
|
|||
const proxyRules = { |
|||
dir: [ |
|||
{ required: true, message: '请输入文件路径', trigger: 'blur' }, |
|||
], |
|||
username: [ |
|||
{ required: true, message: '请输入用户名', trigger: 'blur' } |
|||
], |
|||
password: [ |
|||
{ required: true, message: '请输入密码', trigger: 'blur' }, |
|||
{ min: 6, message: '密码长度至少为6位', trigger: 'blur' } |
|||
] |
|||
}; |
|||
const pageSize = 10; |
|||
const currentPage = ref(1); |
|||
|
|||
const paginatedProxies = computed(() => { |
|||
const start = (currentPage.value - 1) * pageSize; |
|||
const end = start + pageSize; |
|||
return proxies.value.slice(start, end); |
|||
}); |
|||
|
|||
const totalPages = computed(() => Math.ceil(proxies.value.length / pageSize)); |
|||
|
|||
const nextPage = () => { |
|||
if (currentPage.value < totalPages.value) { |
|||
currentPage.value++; |
|||
} |
|||
}; |
|||
|
|||
const prevPage = () => { |
|||
if (currentPage.value > 1) { |
|||
currentPage.value--; |
|||
} |
|||
}; |
|||
</script> |
|||
<template> |
|||
<div> |
|||
<el-row justify="end"> |
|||
<el-button type="primary" :icon="Plus" circle @click="proxyDialogShow = true" /> |
|||
</el-row> |
|||
<el-table :data="paginatedProxies" style="width: 98%;border:none"> |
|||
<el-table-column prop="dir" label="本地路径" width="180" /> |
|||
<el-table-column prop="username" label="用户名" width="180" /> |
|||
<el-table-column label="操作"> |
|||
<template #default="scope"> |
|||
<el-button size="small" @click="editNas(scope.row)">编辑</el-button> |
|||
<el-button size="small" type="danger" @click="deleteNas(scope.row.id)">删除</el-button> |
|||
</template> |
|||
</el-table-column> |
|||
</el-table> |
|||
<el-pagination v-if="totalPages > 1" layout="prev, pager, next" :total="getProxies().length" |
|||
:page-size="pageSize" v-model:current-page="currentPage" @next-click="nextPage" @prev-click="prevPage" /> |
|||
<el-dialog v-model="proxyDialogShow" :title="isEditing ? '编辑Nas服务端' : '添加Nas服务端'" width="400px"> |
|||
<span> |
|||
<el-form :model="proxyData" :rules="proxyRules" ref="pwdRef"> |
|||
<el-form-item label="路径" prop="dir"> |
|||
<el-input v-model="proxyData.dir" @click="selectFile()"/> |
|||
</el-form-item> |
|||
<el-form-item label="用户" prop="username"> |
|||
<el-input v-model="proxyData.username" /> |
|||
</el-form-item> |
|||
<el-form-item label="密码" prop="password"> |
|||
<el-input v-model="proxyData.password" type="password" /> |
|||
</el-form-item> |
|||
<el-form-item> |
|||
<el-button type="primary" @click="saveNas" style="margin: 0 auto;"> |
|||
确认 |
|||
</el-button> |
|||
</el-form-item> |
|||
</el-form> |
|||
</span> |
|||
</el-dialog> |
|||
</div> |
|||
</template> |
@ -0,0 +1,154 @@ |
|||
<script setup lang="ts"> |
|||
import { Plus } from '@element-plus/icons-vue' |
|||
import { ref, computed } from "vue"; |
|||
interface ProxyItem { |
|||
id: number; |
|||
server_url: string; |
|||
disk: string; |
|||
username: string; |
|||
password: string; |
|||
} |
|||
const localKey = "godoos_local_nasclient" |
|||
const getProxies = (): ProxyItem[] => { |
|||
const proxies = localStorage.getItem(localKey); |
|||
return proxies ? JSON.parse(proxies) : []; |
|||
}; |
|||
|
|||
const saveProxies = (proxies: ProxyItem[]) => { |
|||
localStorage.setItem(localKey, JSON.stringify(proxies)); |
|||
}; |
|||
|
|||
const proxies = ref<ProxyItem[]>(getProxies()); |
|||
const initData = { |
|||
id: Date.now(), |
|||
server_url: "", |
|||
disk: "", |
|||
username: "", |
|||
password: "", |
|||
} |
|||
const proxyData = ref<ProxyItem>(initData); |
|||
const proxyDialogShow = ref(false); |
|||
const isEditing = ref(false); |
|||
const pwdRef = ref<any>(null); |
|||
|
|||
const addProxy = () => { |
|||
if (pwdRef.value.validate()) { |
|||
proxies.value.push({ ...proxyData.value }); |
|||
saveProxies(proxies.value); |
|||
proxyDialogShow.value = false; |
|||
proxyData.value = initData; |
|||
} |
|||
}; |
|||
|
|||
const editNas = (proxy: ProxyItem) => { |
|||
proxyData.value = { ...proxy }; |
|||
isEditing.value = true; |
|||
proxyDialogShow.value = true; |
|||
}; |
|||
|
|||
const updateProxy = () => { |
|||
if (pwdRef.value.validate()) { |
|||
const index = proxies.value.findIndex(p => p.id === proxyData.value.id); |
|||
if (index !== -1) { |
|||
proxies.value[index] = { ...proxyData.value }; |
|||
saveProxies(proxies.value); |
|||
proxyDialogShow.value = false; |
|||
proxyData.value = initData; |
|||
isEditing.value = false; |
|||
} |
|||
} |
|||
}; |
|||
const deleteNas = (id: number) => { |
|||
proxies.value = proxies.value.filter(p => p.id !== id); |
|||
saveProxies(proxies.value); |
|||
}; |
|||
|
|||
const saveNas = () => { |
|||
pwdRef.value.validate((valid: boolean) => { |
|||
if (valid) { |
|||
if (isEditing.value) { |
|||
updateProxy(); |
|||
} else { |
|||
addProxy(); |
|||
} |
|||
} else { |
|||
console.log('表单验证失败'); |
|||
} |
|||
}); |
|||
}; |
|||
|
|||
const proxyRules = { |
|||
username: [ |
|||
{ required: true, message: '请输入用户名', trigger: 'blur' } |
|||
], |
|||
password: [ |
|||
{ required: true, message: '请输入密码', trigger: 'blur' }, |
|||
{ min: 6, message: '密码长度至少为6位', trigger: 'blur' } |
|||
] |
|||
}; |
|||
const pageSize = 10; |
|||
const currentPage = ref(1); |
|||
|
|||
const paginatedProxies = computed(() => { |
|||
const start = (currentPage.value - 1) * pageSize; |
|||
const end = start + pageSize; |
|||
return proxies.value.slice(start, end); |
|||
}); |
|||
|
|||
const totalPages = computed(() => Math.ceil(proxies.value.length / pageSize)); |
|||
|
|||
const nextPage = () => { |
|||
if (currentPage.value < totalPages.value) { |
|||
currentPage.value++; |
|||
} |
|||
}; |
|||
|
|||
const prevPage = () => { |
|||
if (currentPage.value > 1) { |
|||
currentPage.value--; |
|||
} |
|||
}; |
|||
</script> |
|||
<template> |
|||
<div> |
|||
<el-row justify="end"> |
|||
<el-button type="primary" :icon="Plus" circle @click="proxyDialogShow = true" /> |
|||
</el-row> |
|||
<el-table :data="paginatedProxies" style="width: 98%;border:none"> |
|||
<el-table-column prop="disk" label="挂载" width="180" /> |
|||
<el-table-column prop="server_url" label="地址" width="180" /> |
|||
<el-table-column prop="username" label="用户名" width="180" /> |
|||
<el-table-column label="操作"> |
|||
<template #default="scope"> |
|||
<el-button size="small" @click="editNas(scope.row)">编辑</el-button> |
|||
<el-button size="small" type="danger" @click="deleteNas(scope.row.id)">删除</el-button> |
|||
</template> |
|||
</el-table-column> |
|||
</el-table> |
|||
<el-pagination v-if="totalPages > 1" layout="prev, pager, next" :total="getProxies().length" |
|||
:page-size="pageSize" v-model:current-page="currentPage" @next-click="nextPage" @prev-click="prevPage" /> |
|||
<el-dialog v-model="proxyDialogShow" :title="isEditing ? '编辑Nas客户端' : '添加Nas客户端'" width="400px"> |
|||
<span> |
|||
<el-form :model="proxyData" :rules="proxyRules" ref="pwdRef"> |
|||
<el-form-item label="挂载" prop="disk"> |
|||
<el-input v-model="proxyData.disk"/> |
|||
</el-form-item> |
|||
<el-form-item label="地址" prop="server_url"> |
|||
<el-input v-model="proxyData.server_url" /> |
|||
</el-form-item> |
|||
<el-form-item label="用户" prop="username"> |
|||
<el-input v-model="proxyData.username" /> |
|||
</el-form-item> |
|||
<el-form-item label="密码" prop="password"> |
|||
<el-input v-model="proxyData.password" type="password" /> |
|||
</el-form-item> |
|||
<el-form-item> |
|||
<el-button type="primary" @click="saveNas" style="margin: 0 auto;"> |
|||
确认 |
|||
</el-button> |
|||
</el-form-item> |
|||
</el-form> |
|||
</span> |
|||
</el-dialog> |
|||
</div> |
|||
</template> |
@ -0,0 +1,33 @@ |
|||
<template> |
|||
<div class="container"> |
|||
<div class="nav"> |
|||
<ul> |
|||
<li v-for="(item, index) in items" :key="index" @click="activeIndex = index" |
|||
:class="{ active: index === activeIndex }"> |
|||
{{ item }} |
|||
</li> |
|||
</ul> |
|||
</div> |
|||
<div class="setting"> |
|||
<div v-if="0 === activeIndex"> |
|||
<LocalNas /> |
|||
</div> |
|||
<div v-if="1 === activeIndex"> |
|||
<NasClient /> |
|||
</div> |
|||
<div v-if="2 === activeIndex"> |
|||
<WebDavClient /> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script lang="ts" setup> |
|||
import { ref } from "vue"; |
|||
const items = ["服务端配置", "NAS客户端", "WebDav客户端"]; |
|||
const activeIndex = ref(0); |
|||
</script> |
|||
|
|||
<style scoped> |
|||
@import "./setStyle.css"; |
|||
</style> |
@ -0,0 +1,154 @@ |
|||
<script setup lang="ts"> |
|||
import { Plus } from '@element-plus/icons-vue' |
|||
import { ref, computed } from "vue"; |
|||
interface ProxyItem { |
|||
id: number; |
|||
url: string; |
|||
disk: string; |
|||
username: string; |
|||
password: string; |
|||
} |
|||
const localKey = "godoos_local_webdav" |
|||
const getProxies = (): ProxyItem[] => { |
|||
const proxies = localStorage.getItem(localKey); |
|||
return proxies ? JSON.parse(proxies) : []; |
|||
}; |
|||
|
|||
const saveProxies = (proxies: ProxyItem[]) => { |
|||
localStorage.setItem(localKey, JSON.stringify(proxies)); |
|||
}; |
|||
|
|||
const proxies = ref<ProxyItem[]>(getProxies()); |
|||
const initData = { |
|||
id: Date.now(), |
|||
url: "", |
|||
disk: "", |
|||
username: "", |
|||
password: "", |
|||
} |
|||
const proxyData = ref<ProxyItem>(initData); |
|||
const proxyDialogShow = ref(false); |
|||
const isEditing = ref(false); |
|||
const pwdRef = ref<any>(null); |
|||
|
|||
const addProxy = () => { |
|||
if (pwdRef.value.validate()) { |
|||
proxies.value.push({ ...proxyData.value }); |
|||
saveProxies(proxies.value); |
|||
proxyDialogShow.value = false; |
|||
proxyData.value = initData; |
|||
} |
|||
}; |
|||
|
|||
const editNas = (proxy: ProxyItem) => { |
|||
proxyData.value = { ...proxy }; |
|||
isEditing.value = true; |
|||
proxyDialogShow.value = true; |
|||
}; |
|||
|
|||
const updateProxy = () => { |
|||
if (pwdRef.value.validate()) { |
|||
const index = proxies.value.findIndex(p => p.id === proxyData.value.id); |
|||
if (index !== -1) { |
|||
proxies.value[index] = { ...proxyData.value }; |
|||
saveProxies(proxies.value); |
|||
proxyDialogShow.value = false; |
|||
proxyData.value = initData; |
|||
isEditing.value = false; |
|||
} |
|||
} |
|||
}; |
|||
const deleteNas = (id: number) => { |
|||
proxies.value = proxies.value.filter(p => p.id !== id); |
|||
saveProxies(proxies.value); |
|||
}; |
|||
|
|||
const saveNas = () => { |
|||
pwdRef.value.validate((valid: boolean) => { |
|||
if (valid) { |
|||
if (isEditing.value) { |
|||
updateProxy(); |
|||
} else { |
|||
addProxy(); |
|||
} |
|||
} else { |
|||
console.log('表单验证失败'); |
|||
} |
|||
}); |
|||
}; |
|||
|
|||
const proxyRules = { |
|||
username: [ |
|||
{ required: true, message: '请输入用户名', trigger: 'blur' } |
|||
], |
|||
password: [ |
|||
{ required: true, message: '请输入密码', trigger: 'blur' }, |
|||
{ min: 6, message: '密码长度至少为6位', trigger: 'blur' } |
|||
] |
|||
}; |
|||
const pageSize = 10; |
|||
const currentPage = ref(1); |
|||
|
|||
const paginatedProxies = computed(() => { |
|||
const start = (currentPage.value - 1) * pageSize; |
|||
const end = start + pageSize; |
|||
return proxies.value.slice(start, end); |
|||
}); |
|||
|
|||
const totalPages = computed(() => Math.ceil(proxies.value.length / pageSize)); |
|||
|
|||
const nextPage = () => { |
|||
if (currentPage.value < totalPages.value) { |
|||
currentPage.value++; |
|||
} |
|||
}; |
|||
|
|||
const prevPage = () => { |
|||
if (currentPage.value > 1) { |
|||
currentPage.value--; |
|||
} |
|||
}; |
|||
</script> |
|||
<template> |
|||
<div> |
|||
<el-row justify="end"> |
|||
<el-button type="primary" :icon="Plus" circle @click="proxyDialogShow = true" /> |
|||
</el-row> |
|||
<el-table :data="paginatedProxies" style="width: 98%;border:none"> |
|||
<el-table-column prop="disk" label="挂载" width="180" /> |
|||
<el-table-column prop="url" label="地址" width="180" /> |
|||
<el-table-column prop="username" label="用户名" width="180" /> |
|||
<el-table-column label="操作"> |
|||
<template #default="scope"> |
|||
<el-button size="small" @click="editNas(scope.row)">编辑</el-button> |
|||
<el-button size="small" type="danger" @click="deleteNas(scope.row.id)">删除</el-button> |
|||
</template> |
|||
</el-table-column> |
|||
</el-table> |
|||
<el-pagination v-if="totalPages > 1" layout="prev, pager, next" :total="getProxies().length" |
|||
:page-size="pageSize" v-model:current-page="currentPage" @next-click="nextPage" @prev-click="prevPage" /> |
|||
<el-dialog v-model="proxyDialogShow" :title="isEditing ? '编辑webdav' : '添加webdav'" width="400px"> |
|||
<span> |
|||
<el-form :model="proxyData" :rules="proxyRules" ref="pwdRef"> |
|||
<el-form-item label="挂载" prop="disk"> |
|||
<el-input v-model="proxyData.disk"/> |
|||
</el-form-item> |
|||
<el-form-item label="地址" prop="url"> |
|||
<el-input v-model="proxyData.url" /> |
|||
</el-form-item> |
|||
<el-form-item label="用户" prop="username"> |
|||
<el-input v-model="proxyData.username" /> |
|||
</el-form-item> |
|||
<el-form-item label="密码" prop="password"> |
|||
<el-input v-model="proxyData.password" type="password" /> |
|||
</el-form-item> |
|||
<el-form-item> |
|||
<el-button type="primary" @click="saveNas" style="margin: 0 auto;"> |
|||
确认 |
|||
</el-button> |
|||
</el-form-item> |
|||
</el-form> |
|||
</span> |
|||
</el-dialog> |
|||
</div> |
|||
</template> |
@ -0,0 +1,15 @@ |
|||
package model |
|||
|
|||
import "gorm.io/gorm" |
|||
|
|||
type ClientUser struct { |
|||
gorm.Model |
|||
ServerUrl string `json:"server_url"` |
|||
DiskId string `json:"disk_id"` |
|||
Username string `json:"username"` |
|||
Password string `json:"password"` |
|||
} |
|||
|
|||
func (*ClientUser) TableName() string { |
|||
return "client_user" |
|||
} |
@ -0,0 +1,27 @@ |
|||
package model |
|||
|
|||
import ( |
|||
"godo/libs" |
|||
|
|||
_ "github.com/ncruces/go-sqlite3/embed" |
|||
"github.com/ncruces/go-sqlite3/gormlite" |
|||
"gorm.io/gorm" |
|||
) |
|||
|
|||
var Db *gorm.DB |
|||
|
|||
func InitDB() { |
|||
dbPath := libs.GetSystemDb() |
|||
db, err := gorm.Open(gormlite.Open(dbPath), &gorm.Config{}) |
|||
if err != nil { |
|||
return |
|||
} |
|||
Db = db |
|||
// 自动迁移模式
|
|||
db.AutoMigrate(&SysDisk{}) |
|||
// 初始化 SysDisk 记录
|
|||
initSysDisk(db) |
|||
db.AutoMigrate(&SysUser{}) |
|||
db.AutoMigrate(&ClientUser{}) |
|||
db.AutoMigrate(&ServerUser{}) |
|||
} |
@ -0,0 +1,14 @@ |
|||
package model |
|||
|
|||
import "gorm.io/gorm" |
|||
|
|||
type LocalProxy struct { |
|||
gorm.Model |
|||
Port uint `json:"port"` |
|||
ProxyType string `json:"proxy_type"` |
|||
Domain string `json:"domain"` |
|||
} |
|||
|
|||
func (*LocalProxy) TableName() string { |
|||
return "local_proxy" |
|||
} |
@ -0,0 +1,16 @@ |
|||
package model |
|||
|
|||
import "gorm.io/gorm" |
|||
|
|||
type ServerUser struct { |
|||
gorm.Model |
|||
DiskId string `json:"disk_id"` |
|||
AuthType string `json:"auth_type"` |
|||
Username string `json:"username"` |
|||
Password string `json:"password"` |
|||
Nickname string `json:"nickname"` |
|||
} |
|||
|
|||
func (*ServerUser) TableName() string { |
|||
return "server_user" |
|||
} |
@ -0,0 +1,59 @@ |
|||
package model |
|||
|
|||
import ( |
|||
"fmt" |
|||
"godo/libs" |
|||
"os" |
|||
"path/filepath" |
|||
|
|||
"gorm.io/gorm" |
|||
) |
|||
|
|||
type SysDisk struct { |
|||
gorm.Model |
|||
Name string `json:"name"` |
|||
Disk string `json:"disk" gorm:"unique"` |
|||
Size int64 `json:"size"` |
|||
Type uint `json:"type"` //0C-E本地 1nasserver 2nasclient 3webdavserver 4webdavclient 5F分享 6B回收站
|
|||
Path string `json:"path"` |
|||
Status uint `json:"status"` |
|||
} |
|||
|
|||
func (*SysDisk) TableName() string { |
|||
return "sys_disk" |
|||
} |
|||
func initSysDisk(db *gorm.DB) { |
|||
var count int64 |
|||
db.Model(&SysDisk{}).Count(&count) |
|||
basePath, err := libs.GetOsDir() |
|||
if err != nil { |
|||
basePath, _ = os.Getwd() |
|||
} |
|||
if count == 0 { |
|||
disks := []SysDisk{ |
|||
{Disk: "B", Name: "回收站", Size: 0, Path: filepath.Join(basePath, "B"), Type: 6, Status: 1}, |
|||
{Disk: "C", Name: "系统", Size: 0, Path: filepath.Join(basePath, "C"), Type: 0, Status: 1}, |
|||
{Disk: "D", Name: "文档", Size: 0, Path: filepath.Join(basePath, "D"), Type: 0, Status: 1}, |
|||
{Disk: "E", Name: "办公", Size: 0, Path: filepath.Join(basePath, "E"), Type: 0, Status: 1}, |
|||
} |
|||
db.Create(&disks) |
|||
fmt.Println("Initialized A-Z disks") |
|||
} |
|||
} |
|||
|
|||
// BeforeDelete 钩子
|
|||
func (sd *SysDisk) BeforeDelete(tx *gorm.DB) (err error) { |
|||
// 不允许删除的磁盘列表
|
|||
nonDeletableDisks := map[string]struct{}{ |
|||
"B": {}, |
|||
"C": {}, |
|||
"D": {}, |
|||
"E": {}, |
|||
"F": {}, |
|||
} |
|||
|
|||
if _, exists := nonDeletableDisks[sd.Disk]; exists { |
|||
return fmt.Errorf("disk %s cannot be deleted", sd.Disk) |
|||
} |
|||
return nil |
|||
} |
@ -0,0 +1,13 @@ |
|||
package model |
|||
|
|||
import "gorm.io/gorm" |
|||
|
|||
type SysUser struct { |
|||
gorm.Model |
|||
Username string `json:"username"` |
|||
Password string `json:"password"` |
|||
} |
|||
|
|||
func (*SysUser) TableName() string { |
|||
return "sys_user" |
|||
} |
@ -0,0 +1,285 @@ |
|||
package sys |
|||
|
|||
import ( |
|||
"fmt" |
|||
"strings" |
|||
) |
|||
|
|||
// FrpConfig 结构体用于存储 FRP 配置
|
|||
type FrpConfig struct { |
|||
ServerAddr string |
|||
ServerPort int |
|||
AuthMethod string |
|||
AuthToken string |
|||
User string |
|||
MetaToken string |
|||
TransportHeartbeatInterval int |
|||
TransportHeartbeatTimeout int |
|||
LogLevel string |
|||
LogMaxDays int |
|||
WebPort int |
|||
TlsConfigEnable bool |
|||
TlsConfigCertFile string |
|||
TlsConfigKeyFile string |
|||
TlsConfigTrustedCaFile string |
|||
TlsConfigServerName string |
|||
ProxyConfigEnable bool |
|||
ProxyConfigProxyUrl string |
|||
} |
|||
|
|||
// Proxy 结构体用于存储代理配置
|
|||
type Proxy struct { |
|||
Name string |
|||
Type string |
|||
LocalIp string |
|||
LocalPort int |
|||
RemotePort int |
|||
CustomDomains []string |
|||
Subdomain string |
|||
BasicAuth bool |
|||
HttpUser string |
|||
HttpPassword string |
|||
StcpModel string |
|||
ServerName string |
|||
BindAddr string |
|||
BindPort int |
|||
FallbackTo string |
|||
FallbackTimeoutMs int |
|||
SecretKey string |
|||
} |
|||
|
|||
// isRangePort 检查端口是否为范围端口
|
|||
func isRangePort(proxy Proxy) bool { |
|||
// 这里假设范围端口的判断逻辑
|
|||
// 你可以根据实际情况调整
|
|||
return strings.Contains(proxy.Name, ":") |
|||
} |
|||
|
|||
// GenFrpcIniConfig 生成 FRP 配置文件内容
|
|||
func GenFrpcIniConfig(config FrpConfig, proxys []Proxy) string { |
|||
var proxyIni []string |
|||
|
|||
for _, m := range proxys { |
|||
rangePort := isRangePort(m) |
|||
ini := fmt.Sprintf("[%s%s]\ntype = \"%s\"\n", |
|||
func() string { |
|||
if rangePort { |
|||
return "range:" |
|||
} |
|||
return "" |
|||
}(), |
|||
m.Name, |
|||
m.Type, |
|||
) |
|||
|
|||
switch m.Type { |
|||
case "tcp", "udp": |
|||
ini += fmt.Sprintf(` |
|||
localIP = "%s" |
|||
localPort = %d |
|||
remotePort = %d |
|||
`, |
|||
m.LocalIp, |
|||
m.LocalPort, |
|||
m.RemotePort, |
|||
) |
|||
case "http", "https": |
|||
ini += fmt.Sprintf(` |
|||
localIP = "%s" |
|||
localPort = %d |
|||
`, |
|||
m.LocalIp, |
|||
m.LocalPort, |
|||
) |
|||
|
|||
if len(m.CustomDomains) > 0 { |
|||
ini += fmt.Sprintf(`custom_domains = [%s] |
|||
`, |
|||
strings.Join(m.CustomDomains, ","), |
|||
) |
|||
} |
|||
|
|||
if m.Subdomain != "" { |
|||
ini += fmt.Sprintf(`subdomain="%s" |
|||
`, |
|||
m.Subdomain, |
|||
) |
|||
} |
|||
if m.BasicAuth { |
|||
ini += fmt.Sprintf(` |
|||
httpUser = "%s" |
|||
httpPassword = "%s" |
|||
`, |
|||
m.HttpUser, |
|||
m.HttpPassword, |
|||
) |
|||
} |
|||
case "stcp", "xtcp", "sudp": |
|||
if m.StcpModel == "visitors" { |
|||
// 访问者
|
|||
ini += fmt.Sprintf(` |
|||
role = visitor |
|||
serverName = "%s" |
|||
bindAddr = "%s" |
|||
bindPort = %d |
|||
`, |
|||
m.ServerName, |
|||
m.BindAddr, |
|||
m.BindPort, |
|||
) |
|||
if m.FallbackTo != "" { |
|||
ini += fmt.Sprintf(` |
|||
fallbackTo = %s |
|||
fallbackTimeoutMs = %d |
|||
`, |
|||
m.FallbackTo, |
|||
m.FallbackTimeoutMs, |
|||
) |
|||
} |
|||
} else if m.StcpModel == "visited" { |
|||
// 被访问者
|
|||
ini += fmt.Sprintf(` |
|||
localIP = "%s" |
|||
localPort = %d |
|||
`, |
|||
m.LocalIp, |
|||
m.LocalPort, |
|||
) |
|||
} |
|||
ini += fmt.Sprintf(` |
|||
sk="%s" |
|||
`, |
|||
m.SecretKey, |
|||
) |
|||
default: |
|||
// 默认情况不做处理
|
|||
} |
|||
|
|||
proxyIni = append(proxyIni, ini) |
|||
} |
|||
|
|||
ini := fmt.Sprintf(`[common] |
|||
serverAddr = %s |
|||
serverPort = %d |
|||
%s |
|||
%s |
|||
%s |
|||
%s |
|||
logFile = "frpc.log" |
|||
logLevel = %s |
|||
logMaxDays = %d |
|||
adminAddr = 127.0.0.1 |
|||
adminPort = %d |
|||
tlsEnable = %t |
|||
%s |
|||
%s |
|||
%s |
|||
%s |
|||
%s |
|||
`, |
|||
config.ServerAddr, |
|||
config.ServerPort, |
|||
func() string { |
|||
if config.AuthMethod == "token" { |
|||
return fmt.Sprintf(` |
|||
authenticationMethod = %s |
|||
token = %s |
|||
`, |
|||
config.AuthMethod, |
|||
config.AuthToken, |
|||
) |
|||
} |
|||
return "" |
|||
}(), |
|||
func() string { |
|||
if config.AuthMethod == "multiuser" { |
|||
return fmt.Sprintf(` |
|||
user = %s |
|||
metaToken = %s |
|||
`, |
|||
config.User, |
|||
config.MetaToken, |
|||
) |
|||
} |
|||
return "" |
|||
}(), |
|||
func() string { |
|||
if config.TransportHeartbeatInterval > 0 { |
|||
return fmt.Sprintf(` |
|||
heartbeatInterval = %d |
|||
`, |
|||
config.TransportHeartbeatInterval, |
|||
) |
|||
} |
|||
return "" |
|||
}(), |
|||
func() string { |
|||
if config.TransportHeartbeatTimeout > 0 { |
|||
return fmt.Sprintf(` |
|||
heartbeatTimeout = %d |
|||
`, |
|||
config.TransportHeartbeatTimeout, |
|||
) |
|||
} |
|||
return "" |
|||
}(), |
|||
config.LogLevel, |
|||
config.LogMaxDays, |
|||
config.WebPort, |
|||
config.TlsConfigEnable, |
|||
func() string { |
|||
if config.TlsConfigEnable && config.TlsConfigCertFile != "" { |
|||
return fmt.Sprintf(` |
|||
tlsCertFile = %s |
|||
`, |
|||
config.TlsConfigCertFile, |
|||
) |
|||
} |
|||
return "" |
|||
}(), |
|||
func() string { |
|||
if config.TlsConfigEnable && config.TlsConfigKeyFile != "" { |
|||
return fmt.Sprintf(` |
|||
tlsKeyFile = %s |
|||
`, |
|||
config.TlsConfigKeyFile, |
|||
) |
|||
} |
|||
return "" |
|||
}(), |
|||
func() string { |
|||
if config.TlsConfigEnable && config.TlsConfigTrustedCaFile != "" { |
|||
return fmt.Sprintf(` |
|||
tlsTrustedCaFile = %s |
|||
`, |
|||
config.TlsConfigTrustedCaFile, |
|||
) |
|||
} |
|||
return "" |
|||
}(), |
|||
func() string { |
|||
if config.TlsConfigEnable && config.TlsConfigServerName != "" { |
|||
return fmt.Sprintf(` |
|||
tlsServerName = %s |
|||
`, |
|||
config.TlsConfigServerName, |
|||
) |
|||
} |
|||
return "" |
|||
}(), |
|||
func() string { |
|||
if config.ProxyConfigEnable { |
|||
return fmt.Sprintf(` |
|||
httpProxy = "%s" |
|||
`, |
|||
config.ProxyConfigProxyUrl, |
|||
) |
|||
} |
|||
return "" |
|||
}(), |
|||
) |
|||
|
|||
ini += strings.Join(proxyIni, "") |
|||
|
|||
return ini |
|||
} |
Loading…
Reference in new issue