Compare commits
2 Commits
92e56e7e88
...
6693acb24a
Author | SHA1 | Date | |
---|---|---|---|
6693acb24a | |||
a0cf66d2e1 |
@ -24,6 +24,7 @@ const projects: { [id: string]: [string, string] } = {
|
|||||||
"capital": ["Capital", "https://git.solsynth.dev/Goatworks/Capital"],
|
"capital": ["Capital", "https://git.solsynth.dev/Goatworks/Capital"],
|
||||||
"passport": ["Hydrogen.Passport", "https://git.solsynth.dev/Hydrogen/Passport"],
|
"passport": ["Hydrogen.Passport", "https://git.solsynth.dev/Hydrogen/Passport"],
|
||||||
"paperclip": ["Hydrogen.Paperclip", "https://git.solsynth.dev/Hydrogen/Paperclip"],
|
"paperclip": ["Hydrogen.Paperclip", "https://git.solsynth.dev/Hydrogen/Paperclip"],
|
||||||
|
"roadsign": ["RoadSign", "https://git.solsynth.dev/Goatworks/RoadSign"],
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
</v-row>
|
</v-row>
|
||||||
</v-sheet>
|
</v-sheet>
|
||||||
<v-img v-else-if="item.mimetype.split('/')[0] == 'image'" :src="getAttachmentUrl(item.rid)" :alt="item.alt"
|
<v-img v-else-if="item.mimetype.split('/')[0] == 'image'" :src="getAttachmentUrl(item.rid)" :alt="item.alt"
|
||||||
class="w-full h-full" cover />
|
class="w-full h-full" :cover="!props.noCover" />
|
||||||
<video v-else-if="item.mimetype.split('/')[0] == 'video'" :src="getAttachmentUrl(item.rid)" class="w-full h-full"
|
<video v-else-if="item.mimetype.split('/')[0] == 'video'" :src="getAttachmentUrl(item.rid)" class="w-full h-full"
|
||||||
controls @click.stop />
|
controls @click.stop />
|
||||||
<v-sheet v-else color="rgba(0, 0, 0, .4)" height="calc(100% + 24px)" class="p-5">
|
<v-sheet v-else color="rgba(0, 0, 0, .4)" height="calc(100% + 24px)" class="p-5">
|
||||||
@ -49,7 +49,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
const config = useRuntimeConfig()
|
const config = useRuntimeConfig()
|
||||||
|
|
||||||
const props = defineProps<{ item: any }>()
|
const props = defineProps<{ item: any, noCover?: boolean }>()
|
||||||
|
|
||||||
const item = computed(() => props.item)
|
const item = computed(() => props.item)
|
||||||
|
|
||||||
|
@ -1,7 +1,48 @@
|
|||||||
---
|
---
|
||||||
thumbnail: /thumbnails/products/roadsign.webp
|
thumbnail: /thumbnails/products/roadsign.webp
|
||||||
title: RoadSign
|
title: RoadSign
|
||||||
description: The reserve proxy that powered our network. Powerful and easy to use.
|
description: The HTTP server that powered us. Great ability, and easy to use
|
||||||
author: [littlesheep]
|
author: [littlesheep]
|
||||||
archived: true
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
RoadSign is an HTTP server developed by Solsynth LLC.
|
||||||
|
Its support for HTTP protocol is not excellent, but it is definitely handy for accelerating your project deployment!
|
||||||
|
It even made us abandon Netlify and Vercel.
|
||||||
|
|
||||||
|
## Highlight Features
|
||||||
|
|
||||||
|
- RoadSign CLI deploys projects with one line of command
|
||||||
|
- Full control over your traffic
|
||||||
|
- Featured Transformer to modify requests
|
||||||
|
- Built-in Warden thread management
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
It is recommended to use docker for installation. The following is an example docker-compose.yml
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
roadsign:
|
||||||
|
image: xsheep2010/roadsign:delta
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- 8000:8000
|
||||||
|
- 81:81
|
||||||
|
volumes:
|
||||||
|
- "/srv/roadsign/config:/config"
|
||||||
|
- "/srv/roadsign/workdir:/workdir"
|
||||||
|
- "/srv/roadsign/settings.toml:/settings.toml"
|
||||||
|
```
|
||||||
|
|
||||||
|
It is recommended to have RoadSign behind a real reverse proxy, so do not listen to 443 and 80 here, use 8000 to let the reverse proxy do the upstream.
|
||||||
|
Port 81 is the management API port that the side-loading API needs to use, which can be changed in the settings.
|
||||||
|
|
||||||
|
It is also recommended to install RoadSign CLI on your local machine
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ npm i -g roadsign-cli
|
||||||
|
```
|
||||||
|
|
||||||
|
## 使用
|
||||||
|
|
||||||
|
Watch the full RoadSign CLI deployment project demo at Asciiema 👉 https://asciinema.org/a/678744
|
||||||
|
@ -1,7 +1,47 @@
|
|||||||
---
|
---
|
||||||
thumbnail: /thumbnails/products/roadsign.webp
|
thumbnail: /thumbnails/products/roadsign.webp
|
||||||
title: RoadSign
|
title: RoadSign
|
||||||
description: 为我们的网络提供动力的反向代理。功能强大,使用方便
|
description: 为我们的网络提供动力的 HTTP 服务器。功能强大,使用方便
|
||||||
author: [littlesheep]
|
author: [littlesheep]
|
||||||
archived: true
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
RoadSign 是由 Solsynth LLC 开发的 HTTP 服务器,其对 HTTP 协议的支持算不上优秀,
|
||||||
|
但是对于加速你的项目部署,一定算得上趁手!甚至让我们抛弃了 Netlify 和 Vercel。
|
||||||
|
|
||||||
|
## 特色
|
||||||
|
|
||||||
|
- RoadSign CLI 一行命令部署项目
|
||||||
|
- 完全控制你的流量
|
||||||
|
- 特色的 Transformer 来修改请求
|
||||||
|
- 内置 Warden 线程管理
|
||||||
|
|
||||||
|
## 安装
|
||||||
|
|
||||||
|
推荐使用 docker 进行安装,以下是示例 docker-compose.yml
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
roadsign:
|
||||||
|
image: xsheep2010/roadsign:delta
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- 8000:8000
|
||||||
|
- 81:81
|
||||||
|
volumes:
|
||||||
|
- "/srv/roadsign/config:/config"
|
||||||
|
- "/srv/roadsign/workdir:/workdir"
|
||||||
|
- "/srv/roadsign/settings.toml:/settings.toml"
|
||||||
|
```
|
||||||
|
|
||||||
|
推荐让 RoadSign 在一个真正的反向代理后,所以在此不监听 443 和 80,使用 8000 让反向代理做上流。
|
||||||
|
其中 81 端口是侧载 API 需要使用的管理 API 端口,可以在设置内修改。
|
||||||
|
|
||||||
|
同时推荐在本地机器上安装 RoadSign CLI
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ npm i -g roadsign-cli
|
||||||
|
```
|
||||||
|
|
||||||
|
## 使用
|
||||||
|
|
||||||
|
在 Asciiema 观看完整的 RoadSign CLI 部署项目演示 👉 https://asciinema.org/a/678744
|
||||||
|
@ -40,7 +40,7 @@
|
|||||||
|
|
||||||
<v-divider class="border-opacity-50 mb-4 mt-0.5" />
|
<v-divider class="border-opacity-50 mb-4 mt-0.5" />
|
||||||
|
|
||||||
<copyright no-centered service="capital" class="px-5" />
|
<copyright no-centered :service="['roadsign', 'capital']" class="px-5" />
|
||||||
|
|
||||||
<footer-links class="px-5 mt-3" />
|
<footer-links class="px-5 mt-3" />
|
||||||
</v-navigation-drawer>
|
</v-navigation-drawer>
|
||||||
|
@ -72,13 +72,20 @@ const breadcrumb = computed(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const navNotRoot = computed(() => route.path.split("/").length > 2)
|
const navNotRoot = computed(() => route.path.split("/").length > 2)
|
||||||
const navQuery = computed(() => ({
|
const navQuery = ref(calcNavQuery())
|
||||||
|
|
||||||
|
function calcNavQuery(path?: string) {
|
||||||
|
return {
|
||||||
where: {
|
where: {
|
||||||
_path: new RegExp("^\\/" + route.path.replace(/^\/|\/$/g, "") + "\\/[^\\/]+\\/?$"),
|
_path: new RegExp("^\\/" + (path ?? route.path).replace(/^\/|\/$/g, "") + "\\/[^\\/]+\\/?$"),
|
||||||
_locale: getLocale(locale),
|
_locale: getLocale(locale),
|
||||||
},
|
},
|
||||||
}))
|
}
|
||||||
console.log(navQuery.value)
|
}
|
||||||
|
|
||||||
|
watch(route, (value) => {
|
||||||
|
navQuery.value = calcNavQuery(value.path)
|
||||||
|
}, { immediate: true, deep: true })
|
||||||
|
|
||||||
function previousNav() {
|
function previousNav() {
|
||||||
const arr = route.path.split("/")
|
const arr = route.path.split("/")
|
||||||
|
24
layouts/minimal.vue
Normal file
24
layouts/minimal.vue
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<template>
|
||||||
|
<v-system-bar flat color="primary" class="px-5 flex justify-center">
|
||||||
|
<v-btn icon="mdi-arrow-left" variant="text" color="white" size="x-small" class="mt-[2px]" @click="goBack" />
|
||||||
|
<h2 class="mt-1">Solsynth LLC</h2>
|
||||||
|
|
||||||
|
<v-spacer />
|
||||||
|
</v-system-bar>
|
||||||
|
|
||||||
|
<v-main>
|
||||||
|
<slot />
|
||||||
|
</v-main>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
|
function goBack() {
|
||||||
|
if (window.history.length > 0) {
|
||||||
|
router.go(-1)
|
||||||
|
} else {
|
||||||
|
navigateTo("/")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
@ -29,9 +29,9 @@
|
|||||||
<v-fab
|
<v-fab
|
||||||
app
|
app
|
||||||
appear
|
appear
|
||||||
|
size="large"
|
||||||
location="bottom end"
|
location="bottom end"
|
||||||
:key="'docs-fab-'+dialogOpen"
|
icon="mdi-menu"
|
||||||
:icon="dialogOpen ? 'mdi-arrow-collapse-right' : 'mdi-menu'"
|
|
||||||
@click="dialogOpen = !dialogOpen"
|
@click="dialogOpen = !dialogOpen"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,5 +1,15 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-container class="content-container mx-auto">
|
<v-row class="h-[calc(100vh-24px)]" no-gutters>
|
||||||
|
<v-col cols="12" md="8">
|
||||||
|
<div class="h-full w-full flex justify-center items-center" :class="isMediumScreen ? 'flex-row' : 'flex-col'">
|
||||||
|
<div class="flex-grow-1 w-full">
|
||||||
|
<attachment-renderer :item="attachment" no-cover />
|
||||||
|
</div>
|
||||||
|
<v-divider v-if="isMediumScreen" vertical />
|
||||||
|
<v-divider v-else />
|
||||||
|
</div>
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12" md="4" class="px-5 pt-3">
|
||||||
<div class="mt-3 mb-4.5 mx-[2.5ch] flex flex-row gap-4 items-center">
|
<div class="mt-3 mb-4.5 mx-[2.5ch] flex flex-row gap-4 items-center">
|
||||||
<nuxt-link :to="`/users/${attachment.account?.name}`">
|
<nuxt-link :to="`/users/${attachment.account?.name}`">
|
||||||
<v-avatar :image="attachment.account?.avatar" />
|
<v-avatar :image="attachment.account?.avatar" />
|
||||||
@ -10,12 +20,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2 class="section-header">Preview</h2>
|
|
||||||
<v-card class="mb-5">
|
|
||||||
<attachment-renderer :item="attachment" />
|
|
||||||
</v-card>
|
|
||||||
|
|
||||||
<h2 class="section-header">Metadata</h2>
|
|
||||||
<v-card class="mb-5">
|
<v-card class="mb-5">
|
||||||
<v-card-text class="flex flex-col gap-4">
|
<v-card-text class="flex flex-col gap-4">
|
||||||
<div class="flex flex-col" v-if="attachment?.alt">
|
<div class="flex flex-col" v-if="attachment?.alt">
|
||||||
@ -52,18 +56,27 @@
|
|||||||
<span>Solar Network Attachment Web Preview</span>
|
<span>Solar Network Attachment Web Preview</span>
|
||||||
<span>Powered by <a class="underline" target="_blank" href="https://git.solsynth.dev/Hydrogen/Paperclip">Hydrogen.Paperclip</a></span>
|
<span>Powered by <a class="underline" target="_blank" href="https://git.solsynth.dev/Hydrogen/Paperclip">Hydrogen.Paperclip</a></span>
|
||||||
</div>
|
</div>
|
||||||
</v-container>
|
</v-col>
|
||||||
|
</v-row>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { useDisplay } from "vuetify"
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const config = useRuntimeConfig()
|
const config = useRuntimeConfig()
|
||||||
|
|
||||||
const firstImage = ref<string | null>()
|
const firstImage = ref<string | null>()
|
||||||
const firstVideo = ref<string | null>()
|
const firstVideo = ref<string | null>()
|
||||||
|
|
||||||
|
const isMediumScreen = useDisplay().mdAndUp
|
||||||
|
|
||||||
const { data: attachment } = await useFetch<any>(`${config.public.solarNetworkApi}/cgi/uc/attachments/${route.params.id}/meta`)
|
const { data: attachment } = await useFetch<any>(`${config.public.solarNetworkApi}/cgi/uc/attachments/${route.params.id}/meta`)
|
||||||
|
|
||||||
|
definePageMeta({
|
||||||
|
layout: "minimal",
|
||||||
|
})
|
||||||
|
|
||||||
if (!attachment.value) {
|
if (!attachment.value) {
|
||||||
throw createError({
|
throw createError({
|
||||||
statusCode: 404,
|
statusCode: 404,
|
||||||
@ -117,17 +130,3 @@ function formatBytes(bytes: number, decimals = 2) {
|
|||||||
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`
|
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.content-container {
|
|
||||||
max-width: 70ch !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-header {
|
|
||||||
margin-left: 2.5ch;
|
|
||||||
margin-right: 2.5ch;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
|
|
||||||
@apply text-lg;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user