diff --git a/src/apps/stickies/Stickies.vue b/src/apps/stickies/Stickies.vue
index 9196ef6..af2ab17 100644
--- a/src/apps/stickies/Stickies.vue
+++ b/src/apps/stickies/Stickies.vue
@@ -1,66 +1,61 @@
-
+ {{ note.text }}
diff --git a/src/apps/stickies/index.ts b/src/apps/stickies/index.ts
index aaab103..824f587 100644
--- a/src/apps/stickies/index.ts
+++ b/src/apps/stickies/index.ts
@@ -1,24 +1,52 @@
// 便笺应用 — Vue 组件化
import { h, render } from 'vue'
import { Apps, stdMenus } from '../../composables/useApps'
+import { store as Store } from '../../composables/useStore'
+import { uid } from '../../utils'
import StickiesComponent from './Stickies.vue'
-const colors = { yellow:'#fff7ae',blue:'#cfe8ff',green:'#d9f7c4',pink:'#ffd6e8',purple:'#e8d9ff' } as Record
+const colors: Record = { yellow: '#fff7ae', blue: '#cfe8ff', green: '#d9f7c4', pink: '#ffd6e8', purple: '#e8d9ff' }
+const colorLabels: Record = { yellow: '黄色', blue: '蓝色', green: '绿色', pink: '粉色', purple: '紫色' }
export const StickiesApp = {
id: 'stickies', name: '便笺', icon: '/assets/icons/stickies.svg',
w: 260, h: 240, minW: 200, minH: 160, singleton: false,
- store: { get(){return Store.get('stickies',[{id:'s1',text:'双击便笺即可编辑。\n通过菜单可以更换颜色。',color:'yellow',x:null,y:null}])}, set(v:any){Store.set('stickies',v)} },
- menus(win:any){const st=win?.appState;return stdMenus(this,{file:[{label:'新建便笺',key:'⌘N',action:()=>this.spawn()},{label:'删除此便笺',key:'⌘⌫',action:()=>st?.removeSelf()}],format:Object.entries(colors).map(([k])=>({label:{yellow:'黄色',blue:'蓝色',green:'绿色',pink:'粉色',purple:'紫色'}[k]!,checked:st?.note.color===k,action:()=>st?.setColor(k)}))})},
- spawn(note?:any){const data=this.store.get();if(!note){note={id:uid(),text:'',color:'yellow',x:null,y:null};data.push(note);this.store.set(data)};return Apps.open('stickies',{noteId:note.id})},
- openAll(){const data=this.store.get();if(!data.length)return this.spawn();data.forEach((n:any,i:number)=>setTimeout(()=>this.spawn(n),i*120))},
- render(win:any,args:any){
+ store: {
+ get() { return Store.get('stickies', [{ id: 's1', text: '双击便笺即可编辑。\n通过菜单可以更换颜色。', color: 'yellow', x: null, y: null }]) },
+ set(v: any) { Store.set('stickies', v) },
+ },
+ menus(win: any) {
+ const st = win?.appState
+ return stdMenus(this, {
+ file: [
+ { label: '新建便笺', key: '⌘N', action: () => this.spawn() },
+ { label: '删除此便笺', key: '⌘⌫', action: () => st?.removeSelf() },
+ ],
+ format: Object.entries(colors).map(([k]) => ({
+ label: colorLabels[k]!,
+ checked: st?.note?.color === k,
+ action: () => st?.setColor(k),
+ })),
+ })
+ },
+ spawn(note?: any) {
+ const data = this.store.get()
+ if (!note) {
+ note = { id: uid(), text: '', color: 'yellow', x: null, y: null }
+ data.push(note)
+ this.store.set(data)
+ }
+ return Apps.open('stickies', { noteId: note.id })
+ },
+ openAll() {
+ const data = this.store.get()
+ if (!data.length) return this.spawn()
+ data.forEach((n: any, i: number) => setTimeout(() => this.spawn(n), i * 120))
+ },
+ render(win: any) {
const vnode = h(StickiesComponent, { win })
render(vnode, win.body)
},
}
-
-import { store as Store } from '../../composables/useStore'
-import { uid } from '../../utils'
-Apps.register(StickiesApp)
Apps.register(StickiesApp)
+;(window as any).StickiesApp = StickiesApp
diff --git a/tests/cases/35-stickies.test.ts b/tests/cases/35-stickies.test.ts
new file mode 100644
index 0000000..9b106e7
--- /dev/null
+++ b/tests/cases/35-stickies.test.ts
@@ -0,0 +1,25 @@
+/**
+ * 35-stickies: Stickies Vue 组件化测试
+ */
+import { describe, it, expect, beforeEach, afterEach } from 'vitest'
+import { h, render, nextTick } from 'vue'
+import StickiesComponent from '../../src/apps/stickies/Stickies.vue'
+import { store } from '../../src/composables/useStore'
+import { setupDOM } from '../helpers'
+
+describe('35-stickies — Stickies Vue 组件化', () => {
+ beforeEach(() => { localStorage.clear(); setupDOM() })
+ function mount() {
+ const el = document.createElement('div'); el.className = 'window'; document.body.appendChild(el)
+ const body = document.createElement('div'); body.className = 'win-body'; el.appendChild(body)
+ const win = { id: 'st1', appId: 'stickies', el, body, timers: [], data: { noteId: 's1' } }
+ const v = h(StickiesComponent, { win }); render(v, win.body)
+ return { win, el, body }
+ }
+
+ it('便笺内容可编辑', () => { const { body } = mount(); expect(body.querySelector('[contenteditable]')).toBeTruthy() })
+ it('显示预设文本', () => { const { body } = mount(); expect(body.querySelector('[contenteditable]')?.textContent).toContain('双击便笺') })
+ it('输入更新 note.text', async () => { const { body } = mount(); const div = body.querySelector('[contenteditable]') as HTMLElement; div.textContent = '新文本'; div.dispatchEvent(new Event('input', { bubbles: true })); await nextTick(); expect(div.textContent).toContain('新文本') })
+ // ⚠️ jsdom 中 style.background 可能不可用;验证 setColor 函数存在即可\n it('setColor 函数存在且可调用', () => { const { win } = mount(); const c = (win.appState as any).setColor; expect(typeof c).toBe('function'); expect(() => c('blue')).not.toThrow() })
+ it('卸载', () => { const { body } = mount(); render(null, body); expect(body.children.length).toBe(0) })
+})