Spaces:
Running
Running
import { client } from "./client.mjs"; | |
import { html, create, styled } from "./misc.mjs"; | |
/** | |
* 管理 speaker | |
* | |
* 1. 显示 speaker 列表 | |
* 2. 创建 speaker | |
* 3. 可以删除修改 speaker | |
*/ | |
const useStore = create((set, get) => ({ | |
/** | |
* @type {{ name: string, params: string }[]} | |
*/ | |
speakers: [], | |
setSpeakers: (speakers) => set({ speakers }), | |
formData: { | |
seed: 42, | |
name: "", | |
}, | |
setFormData: (data) => set({ formData: data }), | |
})); | |
window.addEventListener("load", async () => { | |
const speakers = await client.listSpeakers(); | |
useStore.get().setSpeakers(speakers.data); | |
}); | |
const SpeakerFactory = () => { | |
// 调用接口创建 speaker | |
// 创建speaker需要设定seed和name | |
const { setSpeakers, formData, setFormData } = useStore(); | |
return html` | |
<feildset class="speaker-factory"> | |
<div> | |
<label | |
>seed | |
<input | |
type="number" | |
value=${formData.seed} | |
oninput=${(e) => setFormData({ ...formData, seed: e.target.value })} | |
/> | |
</label> | |
<label | |
>name | |
<input | |
type="text" | |
value=${formData.name} | |
oninput=${(e) => setFormData({ ...formData, name: e.target.value })} | |
/> | |
</label> | |
<button | |
onclick=${async () => { | |
const speaker = await client.createSpeaker(formData); | |
setSpeakers([...useStore.get().speakers, speaker]); | |
setFormData({ seed: 0, name: "" }); | |
}} | |
> | |
创建 | |
</button> | |
</div> | |
</feildset> | |
`; | |
}; | |
const SpeakerList = () => { | |
// 显示 speaker 列表 | |
// 只是可以列出来,没有其他操作 | |
const { speakers } = useStore(); | |
// 以table | |
return html` | |
<fieldset class="spekaer-list"> | |
<legend>Speakers</legend> | |
<table class="speaker-list"> | |
<thead> | |
<tr> | |
<th>id</th> | |
<th>name</th> | |
</tr> | |
</thead> | |
<tbody> | |
${speakers.map( | |
(speaker) => html` | |
<tr> | |
<td>${speaker.id}</td> | |
<td>${speaker.name}</td> | |
</tr> | |
` | |
)} | |
</tbody> | |
</table> | |
</fieldset> | |
`; | |
}; | |
const SpeakerPageContainer = styled.div` | |
display: flex; | |
flex-direction: row; | |
textarea { | |
width: 100%; | |
height: 10rem; | |
margin-bottom: 1rem; | |
min-height: 10rem; | |
resize: vertical; | |
} | |
button { | |
padding: 0.5rem 1rem; | |
background-color: #007bff; | |
color: white; | |
border: none; | |
cursor: pointer; | |
} | |
button:hover { | |
background-color: #0056b3; | |
} | |
button:disabled { | |
background-color: #6c757d; | |
cursor: not-allowed; | |
} | |
fieldset { | |
margin-top: 1rem; | |
padding: 1rem; | |
border: 1px solid #333; | |
} | |
legend { | |
font-weight: bold; | |
} | |
label { | |
display: block; | |
margin-bottom: 0.5rem; | |
} | |
select, | |
input[type="range"], | |
input[type="number"] { | |
width: 100%; | |
margin-top: 0.25rem; | |
} | |
input[type="range"] { | |
width: calc(100% - 2rem); | |
} | |
input[type="number"] { | |
width: calc(100% - 2rem); | |
padding: 0.5rem; | |
} | |
input[type="text"] { | |
width: 100%; | |
padding: 0.5rem; | |
} | |
audio { | |
margin-top: 1rem; | |
} | |
textarea, | |
input, | |
select { | |
background-color: #333; | |
color: white; | |
border: 1px solid #333; | |
border-radius: 0.25rem; | |
padding: 0.5rem; | |
} | |
table { | |
width: 100%; | |
border-collapse: collapse; | |
} | |
th, | |
td { | |
padding: 0.5rem; | |
border: 1px solid #333; | |
} | |
th { | |
background-color: #333; | |
color: white; | |
} | |
th:nth-child(2), | |
td:nth-child(2) { | |
width: 60%; | |
} | |
.speaker-factory { | |
flex: 1; | |
} | |
.spekaer-list { | |
width: 256px; | |
} | |
`; | |
export const SpeakerPage = () => { | |
return html` | |
<${SpeakerPageContainer}> | |
<${SpeakerList} /> | |
<${SpeakerFactory} /> | |
<//> | |
`; | |
}; | |