Skip to content

Commit

Permalink
fix: 列表编辑器
Browse files Browse the repository at this point in the history
  • Loading branch information
yanghua committed Jan 30, 2025
1 parent 55e7e03 commit b3d1ffc
Show file tree
Hide file tree
Showing 9 changed files with 224 additions and 25 deletions.
47 changes: 44 additions & 3 deletions backend/api/memo/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ func NewMemoApi(group fiber.Router) fiber.Router {
memoApi := group.Group("/memo", GetUserInfo)

memoApi.Put("", CreateMemo)
memoApi.Patch("", UpdateMemo)
memoApi.Post("/all", QueryMemos)
memoApi.Post("/:id", QueryMemoById)

Expand All @@ -26,6 +27,11 @@ type MemoCreate struct {
Content string `json:"content"`
}

type MemoUpdate struct {
Content string `json:"content"`
Id string `json:"id"`
}

type MemoQuery struct {
PageNo int64 `json:"pageNo,omitempty"`
PageSize int64 `json:"pageSize,omitempty"`
Expand Down Expand Up @@ -107,7 +113,44 @@ func CreateMemo(c *fiber.Ctx) error {
return c.JSON(memo)
}

func QueryMemo() {}
func UpdateMemo(c *fiber.Ctx) error {

_store, _ := c.Locals("store").(*store.Store)
userId, _ := c.Locals("user_id").(string)
userName, _ := c.Locals("user_name").(string)

// 获取memo的内容
memoUpdate := MemoUpdate{}
err := c.BodyParser(&memoUpdate)

if err != nil {
return err
}

if len(memoUpdate.Content) == 0 {
return errors.New("内容为空")
}

// log.Println(memoCreate.Content)

memo, err := store.UpdateMemo(store.MemoUpdate{
Content: memoUpdate.Content,
Id: memoUpdate.Id,
CreatorId: userId,
}, *_store)

if err != nil {
return err
}

memo.CreatorName = userName

text := []byte(memo.Content)
tokens := parser.Parser(text)
memo.Content = render.RenderToHtml(text, tokens)

return c.JSON(memo)
}

func QueryMemos(c *fiber.Ctx) error {
_store, _ := c.Locals("store").(*store.Store)
Expand Down Expand Up @@ -154,5 +197,3 @@ func QueryMemoById(c *fiber.Ctx) error {

return c.JSON(memo)
}

func UpdateMemo() {}
27 changes: 27 additions & 0 deletions backend/store/memo.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ type MemoCreate struct {
CreatorId string
}

type MemoUpdate struct {
Content string
Id string
CreatorId string
}

type MemoQuery struct {
CreatorId string
PageSize int64
Expand All @@ -52,6 +58,27 @@ func CreateMemo(memoCreate MemoCreate, store Store) (Memo, error) {
return memo, err
}

func UpdateMemo(memoUpdate MemoUpdate, store Store) (Memo, error) {

memo := Memo{
Content: memoUpdate.Content,
CreatorId: memoUpdate.CreatorId,
Id: memoUpdate.Id,
}

err := store.db.QueryRow(
"update memos set content=$1 where id=$2 returning id, create_at, update_at;",
memoUpdate.Content,
memoUpdate.Id,
).Scan(&memo.Id, &memo.CreateAt, &memo.UpdateAt)

if err != nil {
return Memo{}, err
}

return memo, err
}

func QueryMemos(memoQuery MemoQuery, store Store) ([]Memo, error) {

var rows *sql.Rows
Expand Down
4 changes: 2 additions & 2 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@

<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<link rel="icon" type="image/svg+xml" href="/logo.png" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>AI Memos</title>
<title>Writing Hub</title>
</head>

<body>
Expand Down
Binary file added public/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
55 changes: 55 additions & 0 deletions src/api/memo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,61 @@ export async function createMemo(content: string) {
}
}

export async function updateMemo(content: string, id: string) {

const accessToken = localStorage.getItem("access-token") ?? ""

const response = await fetch('/api/memo', {
method: 'PATCH',
headers: {
'content-type': 'application/json',
'authorization': `bearer ${accessToken}`
},
body: JSON.stringify({
content: content,
id
})
})

if (!response.ok) {
return {
code: RequestCode.REQUEST_ERROR,
}
}
const json = await response.json()

return {
code: RequestCode.REQUEST_SUCCESS,
data: json
}
}

export async function getMemoById(id: string) {

const accessToken = localStorage.getItem("access-token") ?? ""

const response = await fetch(`/api/memo/${id}`, {
method: "POST",
headers: {
'content-type': 'application/json',
'authorization': `bearer ${accessToken}`
}
})


if (!response.ok) {
return {
code: RequestCode.REQUEST_ERROR,
}
}
const json = await response.json()

return {
code: RequestCode.REQUEST_SUCCESS,
data: json
}
}

export async function queryMemos(pageNo: number = 1) {

const accessToken = localStorage.getItem("access-token") ?? ""
Expand Down
16 changes: 14 additions & 2 deletions src/ui/Home.vue
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,17 @@ function onCreate(data: any) {
memosList.value = [...dataTransform([data]), ...memosList.value]
}
function onUpdate(memo: any) {
memosList.value = memosList.value.map((_memo) => {
if (_memo.id != memo.id) {
return _memo
} else {
_memo.content = memo.content
return _memo
}
})
}
onMounted(async () => {
isLoading.value = true
const _data = await queryMemos(pageNo.value)
Expand All @@ -101,13 +112,14 @@ onMounted(async () => {
<!-- 首页 -->
<div class="max-w-896px mx-auto flex gap-16px">
<div class="grow">
<Editor @create="onCreate" />
<Editor mode="create" @create="onCreate" />
<div class="mt-16px">
<!-- <div v-if="isLoading"
class="mx-auto relative animate-spin w-20px h-20px rounded-1/2 border-2px bg-gradient-conic bg-gradient-from-blue bg-gradient-to-lime before:(content-[''] absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 rounded-1/2 w-75% h-75% bg-white)">
</div> -->
<!-- memos卡片列表 -->
<MemosCard v-for="memo in memosList" :key="memo.id" v-bind="memo" class="first:mt-0 mt-8px" />
<MemosCard v-for="memo in memosList" @update="onUpdate" :key="memo.id" v-bind="memo"
class="first:mt-0 mt-8px" />

<div v-if="isMore" ref="loading" class="flex flex-col items-center mt-16px">
<div
Expand Down
42 changes: 38 additions & 4 deletions src/ui/editor/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,23 @@ import {
MicVocalIcon
} from 'lucide-vue-next';
import { ref, useTemplateRef } from 'vue';
import { createMemo } from '../../api/memo';
import { createMemo, updateMemo } from '../../api/memo';
import { RequestCode } from '../../api';
import SelectList from '../resources/SelectList.vue';
import { useEventListener } from '@vueuse/core';
const emits = defineEmits(["create"])
const { mode = 'create', memoId, rawContent } = defineProps<{
mode?: 'create' | 'update'
memoId?: string
rawContent?: string
}>()
const emits = defineEmits(["create", "update"])
const loading = ref(false)
const textArea = useTemplateRef("textarea")
const onSubmit = async () => {
const onCreate = async () => {
loading.value = true
const value = textArea.value?.value
Expand All @@ -36,6 +42,33 @@ const onSubmit = async () => {
loading.value = false
}
const onUpdate = async () => {
loading.value = true
const value = textArea.value?.value
if (!value) {
loading.value = false
return
}
const { code, data } = await updateMemo(value, memoId!)
if (code === RequestCode.REQUEST_SUCCESS) {
emits("update", data)
textArea.value.value = ""
}
loading.value = false
}
const onSubmit = async () => {
if (mode === 'create') {
onCreate()
}
if (mode === 'update' && memoId) {
onUpdate()
}
}
const isShowPackage = ref(false)
const onPackageClicked = () => {
isShowPackage.value = !isShowPackage.value
Expand Down Expand Up @@ -63,7 +96,8 @@ useEventListener('click', (event) => {
<template>
<!-- 编辑器 -->
<div class=" bg-#ffffff border-(1px #ececec) shadow-[0_0_4px_#ececec] rounded-8px p-8px">
<textarea placeholder="此刻的想法..." ref="textarea" class="w-full outline-none min-h-[calc(6*1.5em)]" />
<textarea :value="rawContent" placeholder="此刻的想法..." ref="textarea"
class="w-full outline-none min-h-[calc(6*1.5em)]" />
<!-- 快捷键 -->
<div class="flex gap-0px items-center">
<HashIcon class="cursor-pointer p-4px hover:bg-#ececec rounded-8px" :size="24" />
Expand Down
43 changes: 33 additions & 10 deletions src/ui/memos-card/index.vue
Original file line number Diff line number Diff line change
@@ -1,15 +1,37 @@
<script lang="ts" setup>
import { EllipsisVerticalIcon, ListStartIcon, PencilIcon, XIcon } from 'lucide-vue-next';
import Editor from '../editor/index.vue'
import { ref } from 'vue';
import { getMemoById } from '../../api/memo';
defineProps<{
const props = defineProps<{
id: string
author?: string
updateDate: string
content: string
}>()
const emits = defineEmits(["update"])
const isShowEditor = ref(false)
const rawContent = ref("")
const getRawContent = async () => {
// 获取内容
const data = await getMemoById(props.id)
rawContent.value = data.data.content
isShowEditor.value = true
}
const onUpdate = (memo: any) => {
console.log(memo)
emits("update", memo)
isShowEditor.value = false
}
</script>

<template>
<div class="p-8px border-(1px #ececec) bg-#ffffff rounded-8px shadow-[0_0_2px_#ececec]">
<div v-if="!isShowEditor" class="p-8px border-(1px #ececec) bg-#ffffff rounded-8px shadow-[0_0_2px_#ececec]">
<!-- 卡片头部区域 -->
<div class="flex items-center">
<div class="text-0.75em font-600 text-#00009f cursor-pointer">{{ author ? `@${author}` : '' }}</div>
Expand All @@ -19,18 +41,18 @@ defineProps<{
<EllipsisVerticalIcon :size="16"
class="cursor-pointer text-#808080 rounded-1/2 group-hover:bg-#f0f0f0 hover:(bg-#f0f0f0)" />
<div
class="absolute z-99 border-1px rounded-8px px-0.5em py-0.25em bg-#f4f4f5 hidden group-hover:block top-16px right-0px w-100px">
<div class="flex gap-16px items-center cursor-pointer">
<PencilIcon :size="16" />
class="absolute z-99 text-12px border-1px rounded-8px px-0.5em py-0.25em bg-#f4f4f5 hidden group-hover:block top-16px right-0px w-70px">
<div @click="getRawContent" class="flex gap-4px items-center cursor-pointer">
<PencilIcon :size="12" />
<span>编辑</span>
</div>
<div class="flex gap-16px items-center cursor-pointer">
<ListStartIcon :size="16" />
<div class="flex gap-4px items-center cursor-pointer">
<ListStartIcon :size="12" />
<span>置顶</span>
</div>
<div class="w-90% mx-auto h-2px bg-#aaaaaa my-8px"></div>
<div class="flex gap-16px items-center cursor-pointer">
<XIcon :size="16" />
<div class="w-90% mx-auto h-1px bg-#aaaaaa my-8px"></div>
<div class="flex gap-4px items-center cursor-pointer">
<XIcon :size="12" />
<span>删除</span>
</div>
</div>
Expand All @@ -40,4 +62,5 @@ defineProps<{
<!-- 卡片内容区域 -->
<div class="mt-4px whitespace-break-spaces" v-html="content" />
</div>
<Editor @update="onUpdate" :raw-content="rawContent" mode="update" :memo-id="id" v-else />
</template>
15 changes: 11 additions & 4 deletions src/ui/side-nav/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,16 @@ const userInfo = useLocalStorage("user-info", () => {
<!-- 侧边导航 -->
<div class="pl-16px pr-32px">
<div class="py-16px flex items-center">
<img v-if="userInfo.avator" class="w-48px h-48px border-2px rounded-1/2" src="https://picsum.photos/64/64" />
<div v-else class="w-48px h-48px border-2px rounded-1/2 text-1.5em font-600 flex items-center justify-center">M</div>
<div class="ml-8px">Memos</div>
<img v-if="userInfo.avator" class="w-48px h-48px border-2px rounded-1/2"
src="https://picsum.photos/64/64" />
<div v-else
class="w-48px h-48px border-2px rounded-1/2 text-1.5em font-600 flex items-center justify-center">{{
userInfo.username?.[0].toUpperCase() || 'M' }}
</div>
<div class="ml-8px">
<div class="font-600">{{ userInfo.username }}</div>
<div class="text-0.5em text-#acacac">{{ userInfo.email }}</div>
</div>
</div>
<div class="flex flex-col gap-8px">
<div v-if="accessToken !== null" @click="router.push('/')"
Expand All @@ -50,7 +57,7 @@ const userInfo = useLocalStorage("user-info", () => {
<div>探索</div>
</div>
<div @click="router.push('/resources')" v-if="accessToken !== null"
:class="{'bg-#ffffff border-1px shadow-[0_0_2px_0_#f0f0f0]': activatedNames.includes('resources') }"
:class="{ 'bg-#ffffff border-1px shadow-[0_0_2px_0_#f0f0f0]': activatedNames.includes('resources') }"
class="flex items-center gap-4px rounded-16px px-16px py-8px cursor-pointer hover:(bg-#f0f0f0)">
<PackageOpenIcon :size="18" />
<div>资源库</div>
Expand Down

0 comments on commit b3d1ffc

Please sign in to comment.