zhuf vor 2 Jahren
Ursprung
Commit
de4a39bc5f

+ 7 - 0
src/components/RemoteList/index.vue

@@ -96,6 +96,13 @@ watch(
     deep: true,
   }
 )
+
+defineExpose({
+  refresh: () => {
+    onRefresh()
+  },
+})
+
 </script>
 
 <template>

+ 65 - 21
src/pages/admin/indey.vue

@@ -1,7 +1,8 @@
 <script setup lang='ts'>
-import { RouteLocationRaw, useRouter } from 'vue-router'
-import { Status } from '~/store/info'
-import tabContainer from './container.vue'
+import { showConfirmDialog, showFailToast, showSuccessToast } from 'vant';
+import { RouteLocationRaw, useRouter } from 'vue-router';
+import { Status } from '~/store/info';
+import tabContainer from './container.vue';
 
 
 const router = useRouter()
@@ -71,27 +72,57 @@ function getGradeAndSubject({ grade, subject }: { grade: string, subject: string
   queryForm.dc_subject_id = subject
 }
 
+const ListRef = ref()
+function doDelete(item: any) {
+  showConfirmDialog({
+    title: '提示',
+    message:
+      '确定要删除吗?',
+  })
+    .then(() => {
+      request({
+        url: '/dyaw/ctfx/delete',
+        data: {
+          dc_id: item.dc_id
+        }
+      }).then(
+        res => {
+          if (res.code === "1") {
+            showSuccessToast('删除成功')
+            ListRef.value?.refresh()
+          } else {
+            showFailToast('删除失败,请稍后再试')
+          }
+        }
+      )
+    })
+    .catch(() => {
+      showFailToast('已取消')
+    })
+}
 </script>
 
 <template>
   <tab-container>
-  <template #nav>
-    <van-nav-bar title="错题分析" left-text="返回" left-arrow @click-left="onClickLeft" />
-  </template>
-
-  <div class="flex justify-between items-center sticky top-90px z-100 bg-light-50">
-    <van-search v-model="queryForm.dc_keyword" placeholder="请输入搜索关键词" class="flex-auto" background="transparent" />
-    <span class="pr-10px">
-      <multi-tree-select @confirm="getGradeAndSubject"></multi-tree-select>
-    </span>
-  </div>
-
-  <remote-list url="/dyaw/ctfx/index" :d="{
-    ...queryForm,
-  }" class="mt-2 flex-none">
-    <template #default="{ row: d }">
-        <van-cell>
-          <div class="cursor-pointer rounded shadow-dark-100 px-4 py-2 shadow-md drop-shadow-md h-110px space-y-2"
+    <template #nav>
+      <van-nav-bar title="错题分析" left-text="返回" left-arrow @click-left="onClickLeft" />
+    </template>
+
+    <div class="flex justify-between items-center sticky top-90px z-100 bg-light-50">
+      <van-search v-model="queryForm.dc_keyword" placeholder="请输入搜索关键词" class="flex-auto" background="transparent" />
+      <span class="pr-10px">
+        <multi-tree-select @confirm="getGradeAndSubject"></multi-tree-select>
+      </span>
+    </div>
+
+    <remote-list ref="ListRef" url="/dyaw/ctfx/index" :d="{
+      ...queryForm,
+    }" class="mt-2 flex-none px-4">
+      <template #default="{ row: d }">
+
+        <van-swipe-cell>
+
+          <div class="mb-4 cursor-pointer rounded shadow-light-900 px-4 py-2 shadow drop-shadow h-110px space-y-2"
             @click="routerPush({ name: 'admin_indey_detail', params: { id: d.dc_id } })">
             <div class="flex justify-between">
               <div class="flex space-x-2">
@@ -110,7 +141,20 @@ function getGradeAndSubject({ grade, subject }: { grade: string, subject: string
             <div class="text-left text-sm text-gray-500 whitespace-nowrap overflow-ellipsis overflow-hidden">{{
               translateString(d.dc_content) }}</div>
           </div>
-        </van-cell>
+
+
+          <template #right>
+            <div class="h-full flex ml-4px">
+              <div square type="danger" text="删除"
+                class="h-full w-100px flex items-center justify-center text-2xl text-light-50 bg-red-500"
+                @click="doDelete(d)">
+                <i:ep:delete />
+              </div>
+
+            </div>
+          </template>
+        </van-swipe-cell>
+
 
       </template>
     </remote-list>

+ 58 - 80
src/pages/teacher/indey.vue

@@ -1,9 +1,9 @@
 <script setup lang='ts'>
-import { RouteLocationRaw, useRouter } from 'vue-router'
-import { Status } from '~/store/info'
-import user from '~/store/user'
-import tabContainer from './container.vue'
-
+import { showConfirmDialog, showFailToast, showSuccessToast } from 'vant';
+import { RouteLocationRaw, useRouter } from 'vue-router';
+import { Status } from '~/store/info';
+import user from '~/store/user';
+import tabContainer from './container.vue';
 
 const router = useRouter()
 function routerPush(_route: RouteLocationRaw) {
@@ -40,22 +40,34 @@ const queryForm = reactive({
 //     }
 //   })
 // }
-
-// function doDelete() {
-//   request({
-//     url: '/dyaw/ctfx/delete',
-//     data: {
-//       dc_id: multipleSelection.value.map(item => item.dc_id)
-//     }
-//   }).then(
-//     res => {
-//       if (res.code === "1") {
-//         ElMessage.success('删除成功')
-//         doQuery()
-//       }
-//     }
-//   )
-// }
+const ListRef = ref()
+function doDelete(item: any) {
+  showConfirmDialog({
+    title: '提示',
+    message:
+      '确定要删除吗?',
+  })
+    .then(() => {
+      request({
+        url: '/dyaw/ctfx/delete',
+        data: {
+          dc_id: item.dc_id
+        }
+      }).then(
+        res => {
+          if (res.code === "1") {
+            showSuccessToast('删除成功')
+            ListRef.value?.refresh()
+          } else {
+            showFailToast('删除失败,请稍后再试')
+          }
+        }
+      )
+    })
+    .catch(() => {
+      showFailToast('已取消')
+    })
+}
 
 
 // TODO: 临时处理
@@ -91,13 +103,15 @@ function getGradeAndSubject({ grade, subject }: { grade: string, subject: string
       </span>
     </div>
 
-    <remote-list url="/dyaw/ctfx/index" :d="{
+    <remote-list ref="ListRef" url="/dyaw/ctfx/index" :d="{
       ...queryForm,
       sm_id: user.sm_info.sm_id,
-    }" class="mt-2 flex-none">
+    }" class="mt-2 flex-none px-4">
       <template #default="{ row: d }">
-        <van-cell>
-          <div class="cursor-pointer rounded shadow-dark-100 px-4 py-2 shadow-md drop-shadow-md h-110px space-y-2"
+
+        <van-swipe-cell>
+
+          <div class="mb-4 cursor-pointer rounded shadow-light-900 px-4 py-2 shadow drop-shadow h-110px space-y-2"
             @click="routerPush({ name: 'teacher_indey_detail', params: { id: d.dc_id } })">
             <div class="flex justify-between">
               <div class="flex space-x-2">
@@ -116,66 +130,30 @@ function getGradeAndSubject({ grade, subject }: { grade: string, subject: string
             <div class="text-left text-sm text-gray-500 whitespace-nowrap overflow-ellipsis overflow-hidden">{{
               translateString(d.dc_content) }}</div>
           </div>
-        </van-cell>
 
-      </template>
-    </remote-list>
 
-  </tab-container>
-  <!-- <tab-container class="w-full h-full flex flex-col">
-              <div class="flex justify-between items-center">
-                <div class="flex space-x-2">
-                  <el-select clearable size="large" placeholder="年级" v-model="queryForm.dc_grade_id">
-                    <el-option v-for="({ grade_id, grade_name }) in Grade" :key="grade_id" :label="grade_name" :value="grade_id" />
-                  </el-select>
-                  <el-select clearable size="large" placeholder="科目" v-model="queryForm.dc_subject_id">
-                    <el-option v-for="({ subject_id, subject_name }) in Subject" :key="subject_id" :label="subject_name"
-                      :value="subject_id" />
-                  </el-select>
-                  <el-select clearable size="large" placeholder="状态" v-model="queryForm.dc_check">
-                    <el-option v-for="(k) in Object.keys(Status)" :key="k" :label="Status[k]" :value="k" />
-                  </el-select>
-                  <el-input size="large" placeholder="关键字搜索" class="max-w-240px" :suffix-icon="Search"
-                    v-model="queryForm.dc_keyword"></el-input>
-                  <el-button size="large" type="success" @click="routerPush({ name: 'teacher_indey_create' })">新建</el-button>
-                  <el-button size="large" type="danger" @click="doDelete">删除</el-button>
-                </div>
+          <template #right>
+            <div class="h-full flex ml-4px">
+              <div square type="primary" text="编辑" v-if="d.dc_check === '0'||d.dc_check === '2'"
+                class="h-full w-100px flex items-center justify-center text-2xl text-light-50 bg-blue-500"
+                @click="routerPush({ name: 'teacher_indey_edit', params: { id: d.dc_id } })">
+                <i:ep:edit />
+              </div>
+              <div square type="danger" text="删除"
+                class="h-full w-100px flex items-center justify-center text-2xl text-light-50 bg-red-500"
+                @click="doDelete(d)">
+                <i:ep:delete />
               </div>
 
-              <div class="flex-auto flex-col flex mt-4 justify-between">
-                <el-table ref="multipleTableRef" :data="tableData" style="width: 100%" @selection-change="handleSelectionChange">
-                  <el-table-column type="selection" width="55" />
-                  <el-table-column property="dc_title" label="标题" width="auto" show-overflow-tooltip />
-                  <el-table-column property="dc_grade_name" label="年级" width="120" />
-                  <el-table-column property="dc_subject_name" label="科目" width="120" />
-                  <el-table-column property="dc_keyword" label="关键词" width="160" />
-                  <el-table-column property="create_user_realname" label="上传教师" width="120" />
-                  <el-table-column property="create_dateline" label="上传时间" width="180">
-                    <template #default="{ row }">
-                      <span>{{ formatTime(row.create_dateline) }}</span>
-                    </template>
-                  </el-table-column>
-                  <el-table-column property="name" label="状态" width="120">
-                    <template #default="{ row }">
-                      <span :class="row.dc_check === '1' ? 'text-green-500' : row.dc_check === '2' ? 'text-red-500' : 'text-blue-500'">{{ Status[row.dc_check] }}</span>
-                    </template>
-                  </el-table-column>
-                  <el-table-column fixed="right" label="操作" width="120">
-                    <template #default="{ row }">
-                      <el-button link type="primary" size="small"
-                        @click="routerPush({ name: 'teacher_indey_detail', params: { id: row.dc_id } })">查看</el-button>
-                      <el-button link type="primary" size="small" :disabled="row.dc_check !== '0'"
-                        @click="routerPush({ name: 'teacher_indey_edit', params: { id: row.dc_id } })">编辑</el-button>
-                    </template>
-                  </el-table-column>
-                </el-table>
-                <div class="flex justify-end mt-6">
-                  <el-pagination v-model:current-page="queryForm.page" background layout="prev, pager, next"
-                    :total="total"></el-pagination>
-                </div>
+            </div>
+          </template>
+        </van-swipe-cell>
 
-              </div>
-            </tab-container> -->
+
+      </template>
+    </remote-list>
+
+  </tab-container>
 </template>
 
 

+ 36 - 39
src/pages/teacher/indey/create.vue

@@ -1,10 +1,10 @@
 <script setup lang='ts'>
+import { showFailToast, showSuccessToast } from 'vant'
+import { reactive, ref } from 'vue'
 import { useRouter } from 'vue-router'
-import { ref, reactive } from 'vue'
 import { Grade, Subject } from '~/store/info'
 import user from '~/store/user'
 import { REQUEST } from '~/utils/request'
-import { showSuccessToast, showFailToast } from 'vant';
 
 const router = useRouter()
 
@@ -31,38 +31,40 @@ const rules = reactive({
 const submit_loading = ref(false)
 
 const submitForm = async () => {
-    submit_loading.value = true
-    console.log('submit!')
-    const dyaw_ctfx = Object.assign({}, ruleForm, {
-      // dc_grade_name: Grade.find((item) => item.grade_id === ruleForm.dc_grade_id)?.grade_name,
-      // dc_subject_name: Subject.find((item) => item.subject_id === ruleForm.dc_subject_id)?.subject_name,
-      // dc_files: ruleForm.dc_files.map((item) => item.p_url).join(';'),
-      create_user_realname: user.user_realname,
-    })
-
-    request({
-      url: '/dyaw/ctfx/add',
-      data: {
-        dyaw_ctfx,
-      },
-    }).then(
-      res => {
-        if (res.code === '1') {
-          showSuccessToast('添加成功')
-          router.back()
-        } else {
-          showFailToast(res.msg)
-        }
-      }
-    ).catch(
-      err => {
-        showFailToast(err)
-      }
-    ).finally(
-      () => {
-        submit_loading.value = false
+  submit_loading.value = true
+  console.log('submit!')
+  const dyaw_ctfx = Object.assign({}, ruleForm, {
+    // dc_grade_name: Grade.find((item) => item.grade_id === ruleForm.dc_grade_id)?.grade_name,
+    // dc_subject_name: Subject.find((item) => item.subject_id === ruleForm.dc_subject_id)?.subject_name,
+    // dc_files: ruleForm.dc_files.map((item) => item.p_url).join(';'),
+    create_user_realname: user.user_realname,
+    dc_files: fileList.value?.map(item => `${item.res.origin}`).join(';')
+
+  })
+
+  request({
+    url: '/dyaw/ctfx/add',
+    data: {
+      dyaw_ctfx,
+    },
+  }).then(
+    res => {
+      if (res.code === '1') {
+        showSuccessToast('添加成功')
+        router.back()
+      } else {
+        showFailToast(res.msg)
       }
-    )
+    }
+  ).catch(
+    err => {
+      showFailToast(err)
+    }
+  ).finally(
+    () => {
+      submit_loading.value = false
+    }
+  )
 }
 
 
@@ -115,11 +117,6 @@ const afterRead = (fileProxy: any) => {
       }
       fileProxy.status = 'done'
       fileProxy.message = ''
-
-      // emits('update:part', fileList.map((item) => item.res.name + ',' + item.res.url).join(';'))
-      // emits('update:part', fileList.map((item) => item.res.name + ',' + item.res.url).join(';'))
-      // emits('update:modelValue', fileList.map(item => `${item.res.name},${item.res.origin}`).join(';'))
-      ruleForm.dc_files = fileList.value?.map(item => `${item.res.origin}`).join(';')
     }
     else {
       fileProxy.status = 'failed'
@@ -169,7 +166,7 @@ const afterRead = (fileProxy: any) => {
         </van-field>
       </van-cell-group>
       <div class="mt-8">
-        <van-button round block type="primary" native-type="submit" :loading="submit_loading" >
+        <van-button round block type="primary" native-type="submit" :loading="submit_loading">
           提交
         </van-button>
       </div>

+ 208 - 0
src/pages/teacher/indey/edit.vue

@@ -0,0 +1,208 @@
+<script setup lang='ts'>
+import { showFailToast, showSuccessToast } from 'vant'
+import { reactive, ref } from 'vue'
+import { useRouter } from 'vue-router'
+import { Grade, Subject } from '~/store/info'
+import { REQUEST } from '~/utils/request'
+
+const props = defineProps<{
+  id: string
+}>()
+
+
+
+
+const router = useRouter()
+
+
+const ruleForm = reactive({
+  dc_title: '',
+  dc_grade_id: '',
+  dc_subject_id: '',
+  dc_keyword: '',
+  dc_content: '',
+  dc_files: '',
+  //
+  dc_grade_name: '',
+  dc_subject_name: '',
+})
+
+const rules = reactive({
+  dc_title: [{ required: true, message: '标题不能为空', }],
+  dc_grade_id: [{ required: true, message: '年级不能为空', }],
+  dc_subject_id: [{ required: true, message: '科目不能为空', }],
+  dc_keyword: [{ required: true, message: '关键字不能为空', }],
+})
+
+const submit_loading = ref(false)
+
+const submitForm = async () => {
+  submit_loading.value = true
+  console.log('submit!')
+  const dyaw_ctfx = Object.assign({}, ruleForm, {
+    dc_files: fileList.value?.map(item => `${item.res.origin}`).join(';'),
+    dc_check: '0',
+  })
+
+  request({
+    url: '/dyaw/ctfx/edit',
+    data: {
+      dc_id: props.id,
+      dyaw_ctfx,
+    },
+  }).then(
+    res => {
+      if (res.code === '1') {
+        showSuccessToast('编辑成功')
+        router.back()
+      } else {
+        showFailToast(res.msg)
+      }
+    }
+  ).catch(
+    err => {
+      showFailToast(err)
+    }
+  ).finally(
+    () => {
+      submit_loading.value = false
+    }
+  )
+}
+
+
+function onClickLeft() {
+  router.back()
+}
+
+const showGradePicker = ref(false)
+const showSubjectPicker = ref(false)
+
+function onGradeConfirm({ selectedOptions }: {
+  selectedOptions: {
+    grade_id: string;
+    grade_name: string;
+  }[]
+}) {
+  ruleForm.dc_grade_id = selectedOptions[0]?.grade_id
+  ruleForm.dc_grade_name = selectedOptions[0]?.grade_name
+  showGradePicker.value = false
+}
+
+function onSubjectConfirm({ selectedOptions }: {
+  selectedOptions: {
+    subject_id: string;
+    subject_name: string;
+  }[]
+}) {
+  ruleForm.dc_subject_id = selectedOptions[0]?.subject_id
+  ruleForm.dc_subject_name = selectedOptions[0]?.subject_name
+  showSubjectPicker.value = false
+}
+
+
+const fileList = ref<unknown[]>([])
+const afterRead = (fileProxy: any) => {
+  fileProxy.status = 'uploading'
+  fileProxy.message = '上传中...'
+  const { file } = fileProxy
+  REQUEST.upload({
+    url: '/upload/main/file',
+    data: { filedata: file },
+  }).then((res) => {
+    if (res?.code === '1') {
+      // fileList.value.push(res.data)
+      fileProxy.url = `${window.GLOBAL_CONFIG.oss}/${res.data.url}`
+      fileProxy.res = {
+        name: res.data.file_name,
+        url: fileProxy.url,
+        origin: res.data.url,
+      }
+      fileProxy.status = 'done'
+      fileProxy.message = ''
+
+    }
+    else {
+      fileProxy.status = 'failed'
+      fileProxy.message = '上传失败'
+    }
+  }).catch((err) => {
+    console.error(err)
+    fileProxy.status = 'failed'
+    fileProxy.message = '上传失败'
+  })
+}
+
+
+await request({
+  url: '/dyaw/ctfx/detail',
+  data: {
+    dc_id: props.id
+  }
+}).then(
+  res => {
+    if (res.code === "1") {
+      const detail = res.data.one_info
+      const keys = (Object.keys(ruleForm) as Array<keyof typeof ruleForm>)
+      keys.forEach((key) => {
+        if (key === 'dc_files') {
+          fileList.value = !detail[key] ? [] : detail[key].split(';').map((p_url: string) => {
+            return {
+              url: window.GLOBAL_CONFIG.oss + p_url,
+              res: {
+                origin: p_url,
+              }
+            }
+          })
+        }
+        ruleForm[key] = detail[key]
+      })
+    }
+  }
+)
+
+</script>
+
+<template>
+  <div class="w-full h-full flex flex-col">
+    <van-nav-bar title="错题详情" left-text="返回" left-arrow @click-left="onClickLeft" />
+
+    <van-form class="px-2" @submit="submitForm">
+      <van-cell-group inset>
+        <van-field label="标题" prop="dc_title" v-model="ruleForm.dc_title" maxlength="20" show-word-limit
+          :rules="rules.dc_title" required>
+        </van-field>
+        <van-field label="年级" prop="dc_grade_id" v-model="ruleForm.dc_grade_name" is-link readonly
+          @click="showGradePicker = true" :rules="rules.dc_grade_id" required></van-field>
+        <van-popup v-model:show="showGradePicker" position="bottom">
+          <van-picker :columns="Grade"
+            :columns-field-names="{ text: 'grade_name', value: 'grade_id', children: 'children' }"
+            @confirm="onGradeConfirm" @cancel="showGradePicker = false" />
+        </van-popup>
+        <van-field label="科目" prop="dc_subject_id" v-model="ruleForm.dc_subject_name" is-link readonly
+          @click="showSubjectPicker = true" :rules="rules.dc_subject_id" required></van-field>
+        <van-popup v-model:show="showSubjectPicker" position="bottom">
+          <van-picker :columns="Subject"
+            :columns-field-names="{ text: 'subject_name', value: 'subject_id', children: 'children' }"
+            @confirm="onSubjectConfirm" @cancel="showSubjectPicker = false" />
+        </van-popup>
+        <van-field label="关键字" prop="dc_keyword" v-model="ruleForm.dc_keyword" maxlength="10" show-word-limit
+          :rules="rules.dc_keyword" required>
+        </van-field>
+        <van-field label="内容" prop="dc_content" v-model="ruleForm.dc_content" rows="3" autosize type="textarea">
+        </van-field>
+        <van-field label="图片" prop="dc_files">
+          <template #input>
+            <van-uploader v-model="fileList" multiple :after-read="afterRead">
+            </van-uploader>
+          </template>
+        </van-field>
+      </van-cell-group>
+      <div class="mt-8">
+        <van-button round block type="primary" native-type="submit" :loading="submit_loading">
+          提交
+        </van-button>
+      </div>
+    </van-form>
+  </div>
+</template>

+ 6 - 6
src/router/routes/teacher.ts

@@ -30,12 +30,12 @@ export default {
           name: 'teacher_indey_create',
           component: () => import('~/pages/teacher/indey/create.vue')
         },
-        // {
-        //   path: 'edit/:id',
-        //   name: 'teacher_indey_edit',
-        //   component: () => import('~/pages/teacher/indey/edit.vue'),
-        //   props: true
-        // },
+        {
+          path: 'edit/:id',
+          name: 'teacher_indey_edit',
+          component: () => import('~/pages/teacher/indey/edit.vue'),
+          props: true
+        },
         {
           path: 'detail/:id',
           name: 'teacher_indey_detail',

+ 1 - 1
tsconfig.json

@@ -2,7 +2,7 @@
   "compilerOptions": {
     "baseUrl": ".",
     "module": "ESNext",
-    "target": "es2016",
+    "target": "ES2022",
     "lib": ["DOM", "ESNext"],
     "strict": true,
     "esModuleInterop": true,