Skip to content

Commit 930bbb7

Browse files
authored
Merge pull request #29 from pdnode-team/feat/update-chars
Feat/update chars
2 parents 0912d25 + d4f55a9 commit 930bbb7

3 files changed

Lines changed: 209 additions & 3 deletions

File tree

website/src/routes/create/+page.svelte

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@
148148
newCharErrorText = '';
149149
reloadCharacters();
150150
} catch (err: any) {
151-
errorText = err.data.data?.message ?? 'Create failed. Please try again.';
151+
newCharErrorText = err.data.data?.message ?? 'Create failed. Please try again.';
152152
153153
const firstKey = Object.keys(err.data.data)[0];
154154
if (firstKey) {
@@ -200,7 +200,7 @@
200200
<span class="label-text font-medium">Your Character Description</span>
201201
</div>
202202
<textarea
203-
name="characterpDescription"
203+
name="characterDescription"
204204
placeholder="description"
205205
class="textarea w-full"
206206
maxlength="1000"
Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
<script lang="ts">
2+
import { goto } from '$app/navigation';
3+
import { page } from '$app/state';
4+
import pb from '$lib/pocketbase';
5+
import { onMount } from 'svelte';
6+
7+
let charTags = $state<string[]>([]);
8+
let charTagsCurrentInput = $state('');
9+
let charErrorText = $state('');
10+
11+
let record = $state<any>();
12+
13+
function newCharAddTag(e: KeyboardEvent) {
14+
if (e.key === 'Enter' && charTagsCurrentInput.trim()) {
15+
e.preventDefault();
16+
if (charTags.length >= 10) {
17+
charErrorText = 'Maximum of ten tags';
18+
return;
19+
}
20+
// 如果标签不存在则添加
21+
if (!charTags.includes(charTagsCurrentInput.trim())) {
22+
charTags.push(charTagsCurrentInput.trim());
23+
}
24+
charTagsCurrentInput = ''; // 清空输入
25+
}
26+
}
27+
28+
let charName = $state('');
29+
let charDescription = $state('');
30+
let charOrigin = $state('');
31+
let charPictures: FileList | undefined = $state();
32+
33+
const updateCharacter = async () => {
34+
const formData = new FormData();
35+
charErrorText = '';
36+
37+
if (charPictures && charPictures.length !== 0) {
38+
for (let file of charPictures) {
39+
formData.append('images', file);
40+
}
41+
}
42+
43+
formData.append('name', charName)
44+
formData.append('description', charDescription)
45+
formData.append('origin', charOrigin)
46+
charTags.forEach((tag) => {
47+
formData.append('tag_names', tag);
48+
});
49+
50+
formData.append('owner', record.owner);
51+
52+
try {
53+
await pb.collection('characters').update(page.params.id!, formData);
54+
goto(`/characters/${page.params.id}`);
55+
} catch (err: any) {
56+
charErrorText = err.data.data?.message ?? 'Update failed. Please try again.';
57+
58+
const firstKey = Object.keys(err.data.data)[0];
59+
if (firstKey) {
60+
const friendlyMessage = `${firstKey}: ${err.data.data[firstKey].message}`;
61+
console.error(friendlyMessage);
62+
charErrorText = friendlyMessage;
63+
return;
64+
}
65+
}
66+
};
67+
68+
onMount(async () => {
69+
if (!pb.authStore.isValid) {
70+
window.location.pathname = '/login';
71+
return;
72+
}
73+
record = await pb.collection('characters').getOne(page.params.id!);
74+
75+
let rawTags = record.tag_names;
76+
77+
try {
78+
// 如果它是字符串,尝试解析它
79+
if (typeof rawTags === 'string') {
80+
// 如果 rawTags 是 '"单相思"',解析后得到 '单相思'
81+
// 如果 rawTags 是 '["A", "B"]',解析后得到 ['A', 'B']
82+
const parsed = JSON.parse(rawTags);
83+
84+
// 解析后判断结果:是数组直接赋值,是字符串则包装成数组
85+
if (Array.isArray(parsed)) {
86+
charTags = parsed;
87+
} else if (typeof parsed === 'string') {
88+
charTags = [parsed];
89+
}
90+
} else if (Array.isArray(rawTags)) {
91+
// 如果 SDK 已经自动帮你转成了数组
92+
charTags = rawTags;
93+
}
94+
} catch (e) {
95+
// 如果解析失败(比如 rawTags 本身就是个普通字符串 "单相思" 而不是 '"单相思"')
96+
charTags = rawTags ? [rawTags] : [];
97+
}
98+
99+
charName = record.name;
100+
charDescription = record.description;
101+
charOrigin = record.origin;
102+
});
103+
</script>
104+
105+
<div class="flex min-h-[70vh] flex-col items-center justify-center px-4 py-12">
106+
<div class="card w-full max-w-md bg-base-100">
107+
{#if record}
108+
<div class="card-body flex flex-col gap-4 p-8">
109+
<h2 class="mb-2 text-center text-3xl font-bold">Update {record?.name}</h2>
110+
<p class="mb-6 text-center text-base-content/60">
111+
All fields must be filled out unless otherwise specified.
112+
</p>
113+
<div class="flex flex-col gap-4">
114+
<label class="form-control w-full">
115+
<div class="label"><span class="label-text font-medium">Name</span></div>
116+
<input
117+
type="text"
118+
name="characterName"
119+
placeholder="XXXX & YYYY"
120+
class="input-bordered input w-full"
121+
autocomplete="name"
122+
bind:value={charName}
123+
required
124+
/>
125+
</label>
126+
127+
<label class="form-control w-full">
128+
<div class="label">
129+
<span class="label-text font-medium">Description</span>
130+
</div>
131+
<textarea
132+
name="characterDescription"
133+
placeholder="description"
134+
class="textarea w-full"
135+
maxlength="1000"
136+
bind:value={charDescription}
137+
required
138+
></textarea>
139+
</label>
140+
141+
<label class="form-control w-full">
142+
<div class="label"><span class="label-text font-medium">Origin</span></div>
143+
<input
144+
type="text"
145+
name="characterOrigin"
146+
placeholder="https://pdnode.com"
147+
class="input-bordered input w-full"
148+
autocomplete="name"
149+
bind:value={charOrigin}
150+
/>
151+
</label>
152+
153+
<div class="form-control w-full max-w-xs">
154+
<label class="label" for="file-upload">
155+
<span class="label-text">Pictures (Option)</span>
156+
</label>
157+
158+
<input
159+
type="file"
160+
id="file-upload"
161+
class="file-input-bordered file-input w-full file-input-primary"
162+
accept="image/*"
163+
multiple
164+
bind:files={charPictures}
165+
/>
166+
</div>
167+
168+
<div class="flex w-full max-w-sm flex-col">
169+
<div class="label">
170+
<span class="label-text font-medium">Tags (Option)</span>
171+
</div>
172+
173+
<input
174+
type="text"
175+
placeholder="Enter the tags and press Enter...."
176+
class="input-bordered input w-full"
177+
bind:value={charTagsCurrentInput}
178+
onkeydown={newCharAddTag}
179+
/>
180+
181+
<div class="mt-2 flex flex-wrap gap-2">
182+
{#each charTags as tag, i}
183+
<div class="badge gap-2 badge-soft p-3 badge-primary">
184+
{tag}
185+
<button type="button" onclick={() => charTags.splice(i, 1)} class="text-xs"
186+
>✕</button
187+
>
188+
</div>
189+
{/each}
190+
</div>
191+
</div>
192+
193+
<p class="text-red-500">{charErrorText}</p>
194+
195+
<button type="submit" class="btn w-full text-lg btn-primary" onclick={updateCharacter}
196+
>Update</button
197+
>
198+
</div>
199+
</div>
200+
{:else}
201+
<div role="alert" class="alert alert-soft alert-error">
202+
<span>The record could not be found.</span>
203+
</div>
204+
{/if}
205+
</div>
206+
</div>

website/src/routes/edit/cps/[id]/+page.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
const formData = new FormData();
2525
formData.append('name', cpName);
2626
formData.append('description', cpDescription);
27-
formData.append('owner', pb.authStore.record!.id);
27+
formData.append('owner', record.owner);
2828
if (cpPictures && cpPictures.length > 0) {
2929
for (let file of cpPictures) {
3030
formData.append('images', file);

0 commit comments

Comments
 (0)