|
@@ -0,0 +1,259 @@
|
|
|
+/**
|
|
|
+ * 知识库项目编辑
|
|
|
+ */
|
|
|
+
|
|
|
+import { Text, View } from "@tarojs/components";
|
|
|
+
|
|
|
+import PageCustom from "@/components/page-custom/index";
|
|
|
+import NavBarNormal from "@/components/NavBarNormal/index";
|
|
|
+import BottomBar from "@/components/BottomBar";
|
|
|
+
|
|
|
+import IconQ from "@/components/icon/IconQ";
|
|
|
+import IconA from "@/components/icon/IconA";
|
|
|
+
|
|
|
+import IconPlusColor14 from "@/components/icon/IconPlusColor14";
|
|
|
+import IconALink from "@/components/icon/IconALink";
|
|
|
+import IconDeleteGray16 from "@/components/icon/IconDeleteGray16";
|
|
|
+import { useEffect, useState } from "react";
|
|
|
+import IconAImage from "@/components/icon/IconAImage";
|
|
|
+import WemetaTextarea from "@/components/wemeta-textarea";
|
|
|
+import WemetaInput from "@/components/wemeta-input";
|
|
|
+import UploaderGrid from '@/components/UploaderGrid'
|
|
|
+import type { TMediaType } from "@/types/index";
|
|
|
+
|
|
|
+import { uploadFile } from "@/utils/http";
|
|
|
+import { EUploadFileScene } from "@/consts/enum";
|
|
|
+
|
|
|
+import Taro, { useRouter } from "@tarojs/taro";
|
|
|
+import { getCorrectionDetail, editCorrection } from "@/service/correction";
|
|
|
+import { isSuccess } from "@/utils";
|
|
|
+
|
|
|
+type TFormdata = {q:string, a: string, links: string[], mediaList: TMediaType[]}
|
|
|
+
|
|
|
+
|
|
|
+export default function Index() {
|
|
|
+
|
|
|
+ const router = useRouter()
|
|
|
+ const { correctionId } = router.params
|
|
|
+
|
|
|
+ const [formData, setFormData] = useState<TFormdata>(
|
|
|
+ {
|
|
|
+ q: '',
|
|
|
+ a: '',
|
|
|
+ links: [],
|
|
|
+ mediaList: [] //{fileType: 'image',url: 'https://cdn.wehome.cn/cmn/png/53/META-H8UKWHWU-2JNUAG2BARJF55VHU9QS3-YBQGHDAM-IW.png'}
|
|
|
+ }
|
|
|
+ );
|
|
|
+
|
|
|
+ const handleInput = (value: string) => {
|
|
|
+ setFormData({
|
|
|
+ ...formData,
|
|
|
+ q: value,
|
|
|
+ });
|
|
|
+ };
|
|
|
+ const handleValueAInput = (value: string) => {
|
|
|
+ setFormData({
|
|
|
+ ...formData,
|
|
|
+ a: value,
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ // 添加链接
|
|
|
+ const addLink = () => {
|
|
|
+ setFormData({
|
|
|
+ ...formData,
|
|
|
+ links: [...formData.links, ""],
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ // 删除链接
|
|
|
+ const removeLink = (e, index) => {
|
|
|
+ e.stopPropagation();
|
|
|
+ const newLinks = [...formData.links];
|
|
|
+ newLinks.splice(index, 1);
|
|
|
+ setFormData({
|
|
|
+ ...formData,
|
|
|
+ links: newLinks,
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ // 更新单个链接
|
|
|
+ const handleLinkChange = (index:number, value: string) => {
|
|
|
+ const newLinks = [...formData.links];
|
|
|
+ newLinks[index] = value;
|
|
|
+ setFormData({
|
|
|
+ ...formData,
|
|
|
+ links: newLinks,
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleDeleteMedia = (index:number) => {
|
|
|
+ setFormData(prev => ({
|
|
|
+ ...prev,
|
|
|
+ mediaList: prev.mediaList.filter((_, i) => i !== index)
|
|
|
+ }));
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleSubmit = async () => {
|
|
|
+ if(!correctionId){
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if(formData.a.length <= 0){
|
|
|
+ Taro.showToast({title: '请输入回答', icon: 'none'})
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if(formData.q.length <= 0){
|
|
|
+ Taro.showToast({title: '请输入问题描述', icon: 'none'})
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ const dataToSubmit = {
|
|
|
+ answer: formData.a,
|
|
|
+ questions: [formData.q],
|
|
|
+ id: correctionId,
|
|
|
+ links: formData.links.filter(link => link.trim() !== ''),
|
|
|
+ pics: formData.mediaList.map( item => item.url)
|
|
|
+ }
|
|
|
+ console.log(dataToSubmit)
|
|
|
+ const {status} = await editCorrection(correctionId, dataToSubmit)
|
|
|
+ if(isSuccess(status)){
|
|
|
+ Taro.showToast({title: '保存成功', icon: 'none'})
|
|
|
+ setTimeout(() => {
|
|
|
+ Taro.navigateBack()
|
|
|
+ }, 300)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const getQaDetail = async (correctionId: string|number)=> {
|
|
|
+ const {status, data} = await getCorrectionDetail(correctionId)
|
|
|
+ if(isSuccess(status)){
|
|
|
+ setFormData({
|
|
|
+ q: data.questions[0],
|
|
|
+ a: data.answer,
|
|
|
+ links: data.links,
|
|
|
+ mediaList: data.pics.map( pic => {
|
|
|
+ return {fileType: 'image', url: pic}
|
|
|
+ }),
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ const handleChooseMedia = ()=> {
|
|
|
+ Taro.chooseMedia({
|
|
|
+ count: 10,
|
|
|
+ mediaType: ["image"],
|
|
|
+ sourceType: ["album", "camera"],
|
|
|
+ async success(r) {
|
|
|
+ // const tempFiles = r.tempFiles;
|
|
|
+ for (const tempFile of r.tempFiles){
|
|
|
+ const result = await uploadFile(tempFile.tempFilePath, EUploadFileScene.OTHER)
|
|
|
+ if(result?.publicUrl){
|
|
|
+ setFormData(prev => {
|
|
|
+ return {...prev, mediaList: [{fileType:'image', url: result.publicUrl}, ...prev.mediaList]}
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ useEffect(()=> {
|
|
|
+ if(correctionId){
|
|
|
+ getQaDetail(correctionId)
|
|
|
+ }
|
|
|
+
|
|
|
+ }, [correctionId])
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ return (
|
|
|
+ <PageCustom>
|
|
|
+ <NavBarNormal scrollFadeIn backText={'纠错记录'}></NavBarNormal>
|
|
|
+ <View className="w-full pb-120">
|
|
|
+ <View className="p-16">
|
|
|
+ <View className="flex flex-col gap-16">
|
|
|
+ <View className="flex flex-col">
|
|
|
+ <View className="flex items-start gap-8 mb-6">
|
|
|
+ <View className="flex-center h-28">
|
|
|
+ <IconQ />
|
|
|
+ </View>
|
|
|
+ <View className="flex-1 text-14 leading-28">问题描述</View>
|
|
|
+ </View>
|
|
|
+ <View className="">
|
|
|
+ <WemetaTextarea
|
|
|
+ value={formData.q}
|
|
|
+ onInput={handleInput}
|
|
|
+ placeholder="请输入问题描述"
|
|
|
+ />
|
|
|
+ </View>
|
|
|
+ </View>
|
|
|
+
|
|
|
+ {/* 回答 */}
|
|
|
+ <View className="flex flex-col">
|
|
|
+ <View className="flex items-start gap-8 mb-6">
|
|
|
+ <View className="flex-center h-28">
|
|
|
+ <IconA />
|
|
|
+ </View>
|
|
|
+ <View className="flex-1 text-14 leading-28">回答</View>
|
|
|
+ </View>
|
|
|
+ <View>
|
|
|
+ <WemetaTextarea
|
|
|
+ value={formData.a}
|
|
|
+ onInput={handleValueAInput}
|
|
|
+ placeholder="请输入回答"
|
|
|
+ />
|
|
|
+ </View>
|
|
|
+ </View>
|
|
|
+
|
|
|
+ {/* 链接 */}
|
|
|
+ <View className="flex flex-col">
|
|
|
+ <View className="flex items-start gap-8 mb-6">
|
|
|
+ <View className="flex-center h-28">
|
|
|
+ <IconALink />
|
|
|
+ </View>
|
|
|
+ <View className="flex-1 text-14 leading-28">链接</View>
|
|
|
+ <View className="flex-center px-8 gap-4" onClick={addLink}>
|
|
|
+ <IconPlusColor14 />
|
|
|
+ <View className="text-primary">新增</View>
|
|
|
+ </View>
|
|
|
+ </View>
|
|
|
+ <View className="flex flex-col gap-8">
|
|
|
+ {formData.links.map((link, index) => {
|
|
|
+ return (
|
|
|
+ <WemetaInput
|
|
|
+ value={link}
|
|
|
+ onInput={(value) => handleLinkChange(index, value)}
|
|
|
+ suffix={() => (
|
|
|
+ <View onClick={(e) => removeLink(e, index)}>
|
|
|
+ <IconDeleteGray16 />
|
|
|
+ </View>
|
|
|
+ )}
|
|
|
+ placeholder="请输入查看链接,支持长按粘贴..."
|
|
|
+ />
|
|
|
+ );
|
|
|
+ })}
|
|
|
+ </View>
|
|
|
+ </View>
|
|
|
+
|
|
|
+ {/* 图片 */}
|
|
|
+ <View className="flex flex-col">
|
|
|
+ <View className="flex items-start gap-8 mb-6">
|
|
|
+ <View className="flex-center h-28">
|
|
|
+ <IconAImage />
|
|
|
+ </View>
|
|
|
+ <View className="flex-1 text-14 leading-28">图片</View>
|
|
|
+ </View>
|
|
|
+ <UploaderGrid onNewUpload={handleChooseMedia} list = {formData.mediaList} onChange={()=> {}} onDelete={handleDeleteMedia} />
|
|
|
+ </View>
|
|
|
+
|
|
|
+ </View>
|
|
|
+ </View>
|
|
|
+
|
|
|
+ <BottomBar>
|
|
|
+ <View className="button-rounded button-primary flex-1" onClick={handleSubmit}>保存</View>
|
|
|
+ </BottomBar>
|
|
|
+ </View>
|
|
|
+ </PageCustom>
|
|
|
+ );
|
|
|
+}
|