feat(wiki): add community image upload for wiki entities

Support uploading images for Pokemon, Items, and Habitats
Track upload history in new entity_image_uploads table
Update entity cards to display uploaded images and usage ribbons
This commit is contained in:
2026-05-03 01:08:45 +08:00
parent 36e10a06b0
commit 784cbdacd1
23 changed files with 1407 additions and 102 deletions

View File

@@ -330,11 +330,13 @@ CREATE TABLE IF NOT EXISTS items (
dual_dyeable boolean NOT NULL DEFAULT false,
pattern_editable boolean NOT NULL DEFAULT false,
no_recipe boolean NOT NULL DEFAULT false,
image_path text NOT NULL DEFAULT '',
sort_order integer NOT NULL DEFAULT 0 CHECK (sort_order >= 0)
);
ALTER TABLE items ALTER COLUMN usage_id DROP NOT NULL;
ALTER TABLE items ADD COLUMN IF NOT EXISTS no_recipe boolean NOT NULL DEFAULT false;
ALTER TABLE items ADD COLUMN IF NOT EXISTS image_path text NOT NULL DEFAULT '';
ALTER TABLE items DROP COLUMN IF EXISTS no_habitat;
CREATE TABLE IF NOT EXISTS recipes (
@@ -420,6 +422,7 @@ CREATE TABLE IF NOT EXISTS maps (
CREATE TABLE IF NOT EXISTS habitats (
id integer GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
name text NOT NULL UNIQUE,
image_path text NOT NULL DEFAULT '',
sort_order integer NOT NULL DEFAULT 0 CHECK (sort_order >= 0)
);
@@ -532,6 +535,7 @@ ALTER TABLE habitats ADD COLUMN IF NOT EXISTS updated_by_user_id integer REFEREN
ALTER TABLE habitats ADD COLUMN IF NOT EXISTS created_at timestamptz NOT NULL DEFAULT now();
ALTER TABLE habitats ADD COLUMN IF NOT EXISTS updated_at timestamptz NOT NULL DEFAULT now();
ALTER TABLE habitats ADD COLUMN IF NOT EXISTS sort_order integer NOT NULL DEFAULT 0 CHECK (sort_order >= 0);
ALTER TABLE habitats ADD COLUMN IF NOT EXISTS image_path text NOT NULL DEFAULT '';
WITH ordered AS (
SELECT id, (row_number() OVER (ORDER BY created_at, id) * 10)::integer AS next_sort_order
@@ -695,6 +699,37 @@ CREATE INDEX IF NOT EXISTS wiki_edit_logs_entity_idx
CREATE INDEX IF NOT EXISTS wiki_edit_logs_user_id_idx
ON wiki_edit_logs(user_id);
CREATE TABLE IF NOT EXISTS entity_image_uploads (
id integer GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
entity_type text NOT NULL CHECK (entity_type IN ('pokemon', 'items', 'habitats')),
entity_id integer,
entity_name text NOT NULL,
path text NOT NULL UNIQUE,
original_filename text NOT NULL DEFAULT '',
mime_type text NOT NULL CHECK (mime_type IN ('image/png', 'image/jpeg', 'image/webp', 'image/gif')),
byte_size integer NOT NULL CHECK (byte_size > 0),
created_by_user_id integer REFERENCES users(id) ON DELETE SET NULL,
created_at timestamptz NOT NULL DEFAULT now(),
CHECK (length(entity_name) BETWEEN 1 AND 120),
CHECK (path !~ '(^/|\\.\\.)')
);
ALTER TABLE entity_image_uploads DROP CONSTRAINT IF EXISTS entity_image_uploads_entity_type_check;
ALTER TABLE entity_image_uploads ADD CONSTRAINT entity_image_uploads_entity_type_check CHECK (
entity_type IN ('pokemon', 'items', 'habitats')
);
ALTER TABLE entity_image_uploads DROP CONSTRAINT IF EXISTS entity_image_uploads_mime_type_check;
ALTER TABLE entity_image_uploads ADD CONSTRAINT entity_image_uploads_mime_type_check CHECK (
mime_type IN ('image/png', 'image/jpeg', 'image/webp', 'image/gif')
);
CREATE INDEX IF NOT EXISTS entity_image_uploads_entity_idx
ON entity_image_uploads(entity_type, entity_id, created_at DESC, id DESC);
CREATE INDEX IF NOT EXISTS entity_image_uploads_user_idx
ON entity_image_uploads(created_by_user_id);
CREATE TABLE IF NOT EXISTS entity_discussion_comments (
id integer GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
entity_type text NOT NULL CHECK (entity_type IN ('pokemon', 'items', 'recipes', 'habitats')),