mirror of https://github.com/veypi/OneAuth.git
文件编辑 管理 上传
parent
24937738db
commit
e48c269357
File diff suppressed because one or more lines are too long
@ -0,0 +1,67 @@
|
|||||||
|
<!--
|
||||||
|
* FsTree.vue
|
||||||
|
* Copyright (C) 2023 veypi <i@veypi.com>
|
||||||
|
* 2023-10-06 15:35
|
||||||
|
* Distributed under terms of the MIT license.
|
||||||
|
-->
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div :style="{ paddingLeft: depth * 2 + 'rem' }"
|
||||||
|
class="cursor-pointer rounded-full h-8 pr-4 flex items-center hover:bg-gray-100" @click="toggle">
|
||||||
|
<q-icon class="transition-all mx-2" :class="[expand ? 'rotate-90' :
|
||||||
|
'']" style="font-size: 24px;" :name="root.type ===
|
||||||
|
'directory' ? 'v-caret-right' : 'v-file'"> </q-icon>
|
||||||
|
<div>
|
||||||
|
{{ root.filename }}
|
||||||
|
</div>
|
||||||
|
<div class="grow"></div>
|
||||||
|
<div>{{ new Date(root.lastmod).toLocaleString() }}</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="expand">
|
||||||
|
<template v-for="(s, si) of subs" :key="si">
|
||||||
|
<FsTree :root="s" :depth="depth + 1"></FsTree>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import FsTree from './FsTree.vue'
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import oafs, { fileProps } from 'src/libs/oafs';
|
||||||
|
import { util } from 'src/libs';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
let expand = ref(false)
|
||||||
|
let subs = ref([] as fileProps[])
|
||||||
|
|
||||||
|
let props = withDefaults(defineProps<{
|
||||||
|
root: fileProps,
|
||||||
|
depth?: number,
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
depth: 0
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const toggle = () => {
|
||||||
|
if (props.root.type === 'file') {
|
||||||
|
util.goto('/file' + props.root.filename)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!expand.value) {
|
||||||
|
oafs.dav().dir(props.root.filename).then(
|
||||||
|
(e: any) => {
|
||||||
|
subs.value = e
|
||||||
|
expand.value = true
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
expand.value = !expand.value
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
|
|
@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
* evt.ts
|
||||||
|
* Copyright (C) 2023 veypi <i@veypi.com>
|
||||||
|
* 2023-10-08 02:21
|
||||||
|
* Distributed under terms of the MIT license.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
import mitt from "mitt";
|
||||||
|
|
||||||
|
const evt = mitt()
|
||||||
|
export default evt
|
@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
* fs.ts
|
||||||
|
* Copyright (C) 2023 veypi <i@veypi.com>
|
||||||
|
* 2023-10-08 01:55
|
||||||
|
* Distributed under terms of the MIT license.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
import axios from "axios";
|
||||||
|
import { Base64 } from 'js-base64'
|
||||||
|
import util from "./util";
|
||||||
|
import { createClient, WebDAVClient } from 'webdav'
|
||||||
|
|
||||||
|
export interface fileProps {
|
||||||
|
filename: string,
|
||||||
|
basename: string,
|
||||||
|
lastmod: string,
|
||||||
|
size: number,
|
||||||
|
type: "directory" | "file",
|
||||||
|
etag: string
|
||||||
|
}
|
||||||
|
|
||||||
|
let cfg = {
|
||||||
|
token: '',
|
||||||
|
host: '',
|
||||||
|
dav: {} as WebDAVClient,
|
||||||
|
}
|
||||||
|
|
||||||
|
const setCfg = (token: string) => {
|
||||||
|
cfg.token = token
|
||||||
|
cfg.dav = createClient('/file/',
|
||||||
|
{ headers: { auth_token: cfg.token } })
|
||||||
|
}
|
||||||
|
|
||||||
|
const rename = (o: string, n?: string) => {
|
||||||
|
let ext = '.' + o.split('.').pop()?.toLowerCase()
|
||||||
|
if (n) {
|
||||||
|
return n + ext
|
||||||
|
}
|
||||||
|
let d = new Date().getTime()
|
||||||
|
return d + Base64.encode(o) + ext
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const get = (url: string): Promise<string> => {
|
||||||
|
return fetch(url, { headers: { auth_token: util.getToken() } }).then((response) => response.text())
|
||||||
|
}
|
||||||
|
|
||||||
|
const upload = (f: FileList | File[], renames?: string[]) => {
|
||||||
|
return new Promise<string[]>((resolve, reject) => {
|
||||||
|
var data = new FormData();
|
||||||
|
for (let i = 0; i < f.length; i++) {
|
||||||
|
let nf = renames ? new File([f[i]], rename(f[i].name, renames[i]), { type: f[i].type }) : f[i]
|
||||||
|
data.append('files', nf, nf.name)
|
||||||
|
}
|
||||||
|
axios.post("/api/upload/", data, {
|
||||||
|
headers: {
|
||||||
|
"Content-Type": 'multipart/form-data',
|
||||||
|
'auth_token': cfg.token,
|
||||||
|
}
|
||||||
|
}).then(e => {
|
||||||
|
resolve(e.data)
|
||||||
|
}).catch(reject)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const dav = () => {
|
||||||
|
return {
|
||||||
|
stat: cfg.dav.stat,
|
||||||
|
dir: cfg.dav.getDirectoryContents,
|
||||||
|
upload: (dir: string, name: string, file: any) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
let reader = new FileReader()
|
||||||
|
reader.onload = function(event) {
|
||||||
|
var res = event.target?.result
|
||||||
|
// let data = new Blob([res])
|
||||||
|
cfg.dav.putFileContents(name, res).then(e => {
|
||||||
|
resolve(e)
|
||||||
|
}).catch(reject)
|
||||||
|
}
|
||||||
|
reader.readAsArrayBuffer(file)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
setCfg,
|
||||||
|
get,
|
||||||
|
upload,
|
||||||
|
dav,
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
<!--
|
||||||
|
* doc.vue
|
||||||
|
* Copyright (C) 2023 veypi <i@veypi.com>
|
||||||
|
* 2023-10-07 22:07
|
||||||
|
* Distributed under terms of the MIT license.
|
||||||
|
-->
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h1 class="page-h1">文档中心</h1>
|
||||||
|
<div class="mx-8 mt-10">
|
||||||
|
<template v-for="(doc, i) in Docs" :key="i">
|
||||||
|
<div class="mb-10">
|
||||||
|
<div class="text-xl flex items-center mb-4">
|
||||||
|
<q-icon class="mx-2" :name="doc.icon"></q-icon>
|
||||||
|
<span>{{ doc.name }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex gap-8">
|
||||||
|
<template v-for="item in doc.items" :key="item.name">
|
||||||
|
<q-chip class="" clickable outline @click="$router.push({
|
||||||
|
name: 'doc_item',
|
||||||
|
params: { url: item.url, typ: 'public' }
|
||||||
|
})" icon="bookmark" color="none">
|
||||||
|
<span>{{ item.name }}</span>
|
||||||
|
</q-chip>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
<q-separator class="mt-6" inset></q-separator>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { DocGroup } from 'src/models';
|
||||||
|
import { ref } from 'vue';
|
||||||
|
const Docs = ref<DocGroup[]>([
|
||||||
|
{
|
||||||
|
name: '用户',
|
||||||
|
icon: 'v-team',
|
||||||
|
items: [
|
||||||
|
{ name: '用户注册授权过程', url: '' },
|
||||||
|
{ name: '用户角色与权限', url: '' },
|
||||||
|
{ name: 'api文档', url: '' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "应用",
|
||||||
|
icon: 'v-apps',
|
||||||
|
items: [
|
||||||
|
{ name: '应用创建及基本设置', url: '' },
|
||||||
|
{ name: '应用权限设置', url: '' },
|
||||||
|
{ name: '应用对接oa流程', url: '' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "系统使用",
|
||||||
|
icon: "v-setting",
|
||||||
|
items: [
|
||||||
|
{ name: "编辑器使用及语法", url: 'markdown.md' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
])
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
|
|
@ -0,0 +1,64 @@
|
|||||||
|
<!--
|
||||||
|
* docItem.vue
|
||||||
|
* Copyright (C) 2023 veypi <i@veypi.com>
|
||||||
|
* 2023-10-07 22:16
|
||||||
|
* Distributed under terms of the MIT license.
|
||||||
|
-->
|
||||||
|
<template>
|
||||||
|
<div class="w-full h-full">
|
||||||
|
<h1 class="page-h1">文档中心</h1>
|
||||||
|
<div>
|
||||||
|
{{ url }}
|
||||||
|
</div>
|
||||||
|
<q-inner-loading :showing="!visible" label="Please wait..." label-class="text-teal" label-style="font-size: 1.1em" />
|
||||||
|
<Editor v-if='doc' eid='doc' preview :content="doc"></Editor>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import msg from '@veypi/msg';
|
||||||
|
import Editor from 'src/components/editor'
|
||||||
|
import oafs from 'src/libs/oafs';
|
||||||
|
import { computed, watch, onMounted, ref } from 'vue';
|
||||||
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
|
let doc = ref('')
|
||||||
|
|
||||||
|
|
||||||
|
const visible = ref(false)
|
||||||
|
let route = useRoute()
|
||||||
|
let router = useRouter()
|
||||||
|
|
||||||
|
let url = computed(() => {
|
||||||
|
if (route.params.typ === 'public') {
|
||||||
|
return '/doc/' + route.params.url
|
||||||
|
}
|
||||||
|
return route.params.url
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(url, u => {
|
||||||
|
render(u as string)
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
const render = (url: string) => {
|
||||||
|
console.log(url)
|
||||||
|
if (!url) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
oafs.get(url).then((value) => {
|
||||||
|
doc.value = value
|
||||||
|
visible.value = true
|
||||||
|
}).catch(e => {
|
||||||
|
console.warn(e)
|
||||||
|
msg.Warn('访问文档地址不存在')
|
||||||
|
router.back()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
onMounted(() => {
|
||||||
|
render(url.value as string)
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
|
|
||||||
|
|
@ -0,0 +1,31 @@
|
|||||||
|
<!--
|
||||||
|
* fsFile.vue
|
||||||
|
* Copyright (C) 2023 veypi <i@veypi.com>
|
||||||
|
* 2023-10-08 05:12
|
||||||
|
* Distributed under terms of the MIT license.
|
||||||
|
-->
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h1 class="page-h1">云文件中心</h1>
|
||||||
|
<div class="px-4">
|
||||||
|
<FsTree v-if="root.filename" :root="root"></FsTree>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import FsTree from 'src/components/FsTree.vue';
|
||||||
|
import oafs, { fileProps } from 'src/libs/oafs';
|
||||||
|
import { onMounted, ref } from 'vue';
|
||||||
|
let root = ref({} as fileProps)
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
oafs.dav().stat('/').then(e => {
|
||||||
|
console.log(e)
|
||||||
|
root.value = e as fileProps
|
||||||
|
})
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
|
|
@ -0,0 +1,19 @@
|
|||||||
|
<!--
|
||||||
|
* settings.vue
|
||||||
|
* Copyright (C) 2023 veypi <i@veypi.com>
|
||||||
|
* 2023-10-08 06:10
|
||||||
|
* Distributed under terms of the MIT license.
|
||||||
|
-->
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h1 class="page-h1">系统设置</h1>
|
||||||
|
<div class="px-4">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
|
|
@ -0,0 +1,17 @@
|
|||||||
|
<!--
|
||||||
|
* user.vue
|
||||||
|
* Copyright (C) 2023 veypi <i@veypi.com>
|
||||||
|
* 2023-10-08 05:31
|
||||||
|
* Distributed under terms of the MIT license.
|
||||||
|
-->
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h1 class="page-h1">账号设置</h1>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
|
|
Loading…
Reference in New Issue