code lint

This commit is contained in:
2025-03-06 00:12:38 +08:00
parent 6d6c69cf37
commit b1593b1c8e
11 changed files with 104 additions and 80 deletions

View File

@@ -35,62 +35,62 @@ http.interceptors.response.use(
},
)
export class Account {
static async login(username: string, password: string) {
export const Account = {
async login(username: string, password: string) {
const res = await http.post("/account/login", { username, password })
return res.data
}
},
static async logout() {
async logout() {
const res = await http.post("/account/logout")
return res.data
}
},
static async getMyProfile() {
async getMyProfile() {
const res = await http.get("/account/profile")
return res.data
}
},
static async list(query: { username: string; page: number }) {
async list(query: { username: string; page: number }) {
const res = await http.get("/account/list", {
params: query,
})
return res.data
}
},
static async toggleActive(id: number) {
async toggleActive(id: number) {
const res = await http.put(`/account/active/${id}`)
return res.data
}
},
}
export class Tutorial {
static async list() {
export const Tutorial = {
async list() {
const res = await http.get("/tutorial/list")
return res.data
}
},
static async createOrUpdate(payload: TutorialIn) {
async createOrUpdate(payload: TutorialIn) {
const res = await http.post("/tutorial/", payload)
return res.data
}
},
static async togglePublic(display: number) {
async togglePublic(display: number) {
const res = await http.put(`/tutorial/public/${display}`)
return res.data
}
},
static async remove(display: number) {
async remove(display: number) {
await http.delete(`/tutorial/${display}`)
}
},
static async get(display: number) {
async get(display: number) {
const res = await http.get(`/tutorial/${display}`)
return res.data
}
},
static async listDisplay() {
async listDisplay() {
const res = await http.get("/tutorial/display")
return res.data
}
},
}

View File

@@ -32,13 +32,9 @@ const props = withDefaults(defineProps<Props>(), {
const code = defineModel<string>("value")
const lang = computed(() => {
if (props.language === "html") {
return html()
} else if (props.language === "css") {
return css()
} else {
return javascript()
}
if (props.language === "html") return html()
if (props.language === "css") return css()
return javascript()
})
</script>
<template>

View File

@@ -4,7 +4,7 @@
<Icon icon="noto:eyes" :width="20"></Icon>
<n-text class="titleText">预览</n-text>
</n-flex>
<n-button quaternary @click="download">下载</n-button>
<n-button quaternary @click="download" :disabled="!showDL">下载</n-button>
</n-flex>
<iframe class="iframe" ref="iframe"></iframe>
</template>
@@ -12,10 +12,11 @@
<script lang="ts" setup>
import { watchDebounced } from "@vueuse/core"
import { html, css, js } from "../store/editors"
import { onMounted, useTemplateRef } from "vue"
import { computed, onMounted, useTemplateRef } from "vue"
import { Icon } from "@iconify/vue"
const iframe = useTemplateRef<HTMLIFrameElement>("iframe")
const showDL = computed(() => html.value || css.value || js.value)
function getContent() {
return `<!DOCTYPE html>
@@ -37,10 +38,12 @@ function getContent() {
function preview() {
if (!iframe.value) return
const doc = iframe.value.contentDocument!
doc.open()
doc.write(getContent())
doc.close()
const doc = iframe.value.contentDocument
if (doc) {
doc.open()
doc.write(getContent())
doc.close()
}
}
function download() {

View File

@@ -75,8 +75,8 @@ async function getContent() {
function addButton() {
const action = document.createElement("div")
action.className = "codeblock-action"
const pres = $content.value!.querySelectorAll("pre")
pres.forEach((pre) => {
const pres = $content.value?.querySelectorAll("pre") ?? []
for (const pre of pres) {
let timer = 0
const copy = action.cloneNode() as HTMLDivElement
pre.insertBefore(copy, pre.children[0])
@@ -88,7 +88,7 @@ function addButton() {
const btn = copy.children[1] as HTMLDivElement
btn.onclick = () => {
tab.value = lang
const content = pre.children[1].textContent!
const content = pre.children[1].textContent
if (lang === "html") html.value = content
if (lang === "css") css.value = content
if (lang === "js") js.value = content
@@ -99,12 +99,14 @@ function addButton() {
btn.innerHTML = "替换"
}, 1000)
}
})
}
}
function modifyLink() {
const links = $content.value!.querySelectorAll("a")
links.forEach((link) => (link.target = "_blank"))
const links = $content.value?.querySelectorAll("a") ?? []
for (const link of links) {
link.target = "_blank"
}
}
async function render() {

View File

@@ -1,10 +1,6 @@
<template>
<n-flex>
<n-button
secondary
v-if="user.role !== Role.Super"
@click="edit"
>
<n-button secondary v-if="user.role !== Role.Super" @click="edit">
修改
</n-button>
<n-button

View File

@@ -2,8 +2,6 @@ import { createApp } from "vue"
import { create } from "naive-ui"
import App from "./App.vue"
//@ts-ignore
import "normalize.css"
//@ts-ignore
import "github-markdown-css/github-markdown-light.css"

View File

@@ -2,11 +2,21 @@
<n-flex vertical class="container">
<n-flex>
<div>
<n-input v-model:value="query.username" clearable />
<n-input
style="width: 200px"
v-model:value="query.username"
clearable
/>
</div>
<div>
<n-select
style="width: 120px"
v-model:value="query.role"
:options="roles"
/>
</div>
<n-button @click="init">搜索</n-button>
<n-button @click="goDjangoUserAdd">新建一个</n-button>
<n-button>批量新建</n-button>
<n-button @click="showBatch = true">批量新建</n-button>
<n-pagination
v-model:page="query.page"
:page-size="20"
@@ -15,6 +25,20 @@
/>
</n-flex>
<n-data-table :columns="columns" :data="users"></n-data-table>
<n-modal
style="width: 300px"
:mask-closable="false"
preset="card"
title="批量新建用户"
v-model:show="showBatch"
>
<n-flex vertical>
<b>前缀web</b>
<n-input placeholder="班级" />
<n-input rows="20" type="textarea" />
<n-button type="primary">提交</n-button>
</n-flex>
</n-modal>
</n-flex>
</template>
<script lang="ts" setup>
@@ -22,10 +46,11 @@ import { onMounted, reactive, ref, h, watch } from "vue"
import { Account } from "../api"
import { parseTime } from "../utils/helper"
import type { DataTableColumn } from "naive-ui"
import { getRole, type User } from "../utils/type"
import { getRole, Role, type User } from "../utils/type"
import { ADMIN_URL } from "../utils/const"
import UserActions from "../components/dashboard/UserActions.vue"
import { useRoute, useRouter } from "vue-router"
import { watchDebounced } from "@vueuse/core"
const users = ref([])
const count = ref(0)
@@ -34,7 +59,16 @@ const router = useRouter()
const query = reactive({
username: "",
page: Number(route.params.page),
role: "",
})
const showBatch = ref(true)
const roles = [
{ label: "全部权限", value: "" },
{ label: "普通用户", value: Role.Normal },
{ label: "管理员", value: Role.Admin },
{ label: "超级管理员", value: Role.Super },
]
const columns: DataTableColumn<User>[] = [
{
@@ -80,7 +114,8 @@ async function init() {
count.value = data.count
}
watch(query, init)
watch(() => [query.page, query.role], init)
watchDebounced(() => query.username, init, { debounce: 500, maxWait: 1000 })
watch(
() => query.page,
(v) => router.push({ params: { page: v } }),