bzkf3 2 years ago
parent
commit
ee63317f6a

+ 1 - 0
package.json

@@ -24,6 +24,7 @@
     "axios": "^1.3.6",
     "element-plus": "^2.3.4",
     "tinymce": "^6.4.2",
+    "vant": "^4.5.0",
     "vue": "^3.2.47",
     "vue-router": "^4.1.6"
   },

+ 26 - 0
pnpm-lock.yaml

@@ -22,6 +22,9 @@ dependencies:
   tinymce:
     specifier: ^6.4.2
     version: 6.4.2
+  vant:
+    specifier: ^4.5.0
+    version: 4.5.0(vue@3.2.47)
   vue:
     specifier: ^3.2.47
     version: 3.2.47
@@ -753,6 +756,18 @@ packages:
       eslint-visitor-keys: 3.4.0
     dev: true
 
+  /@vant/popperjs@1.3.0:
+    resolution: {integrity: sha512-hB+czUG+aHtjhaEmCJDuXOep0YTZjdlRR+4MSmIFnkCQIxJaXLQdSsR90XWvAI2yvKUI7TCGqR8pQg2RtvkMHw==}
+    dev: false
+
+  /@vant/use@1.5.1(vue@3.2.47):
+    resolution: {integrity: sha512-Zxd7lDz/LliVYEQi3PR9a8CQa/kGCVzF0u9hqDMaTlgXlbG0wHMFPllrcG0ThR6bfs8xrYVuSFM9pJn6HSoUGQ==}
+    peerDependencies:
+      vue: ^3.0.0
+    dependencies:
+      vue: 3.2.47
+    dev: false
+
   /@vitejs/plugin-vue@4.2.1(vite@4.3.3)(vue@3.2.47):
     resolution: {integrity: sha512-ZTZjzo7bmxTRTkb8GSTwkPOYDIP7pwuyV+RV53c9PYUouwcbkIZIvWvNWlX2b1dYZqtOv7D6iUAnJLVNGcLrSw==}
     engines: {node: ^14.18.0 || >=16.0.0}
@@ -3371,6 +3386,17 @@ packages:
       spdx-expression-parse: 3.0.1
     dev: true
 
+  /vant@4.5.0(vue@3.2.47):
+    resolution: {integrity: sha512-MK7TlTvp+n0HRFAi7SoRZwTt1pquJ2aUa8nQ899Mf+x9gi8OLYrMFqEQX+l1e4Cl4RO0vD1Q5w9rs4+Wehesog==}
+    peerDependencies:
+      vue: ^3.0.0
+    dependencies:
+      '@vant/popperjs': 1.3.0
+      '@vant/use': 1.5.1(vue@3.2.47)
+      '@vue/shared': 3.2.47
+      vue: 3.2.47
+    dev: false
+
   /vite-plugin-windicss@1.8.10(vite@4.3.3):
     resolution: {integrity: sha512-scywsuzo46lcTBohspmF0WiwhWEte6p+OUVrX4yr7VMRvLHMHVfLtJReyD5pppjijG7YOwVsZn7XBWWZtF658Q==}
     peerDependencies:

+ 10 - 18
src/App.vue

@@ -1,32 +1,29 @@
 <script setup lang="ts">
-import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
-import { ElMessage } from 'element-plus';
+// import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
+// import { ElMessage } from 'element-plus';
+import { showFailToast } from 'vant';
 import { UserRole } from '~/store/user';
 
 if (UserRole === 'other') {
-  ElMessage.error('非法用户')
+  showFailToast('非法用户')
 }
 
 </script>
 
 <template>
-  <el-config-provider :message="{ max: 3 }" :z-index="100" :locale="zhCn" namespace="ep">
+  <van-config-provider :z-index="100">
     <suspense>
-      <div class="bg w-full h-672px flex justify-center items-center overflow-y-auto">
-        <!-- try to fix auto complete -->
-        <div class="hidden">
-          <input type="text">
-          <input type="text">
-          <input type="text">
-        </div>
+      <div class="w-screen h-screen flex flex-col justify-center items-center overflow-y-auto">
         <router-view></router-view>
       </div>
 
       <template #fallback>
-        <div v-loading="true" class="w-full h-672px" />
+        <div class="w-screen h-screen flex justify-center items-center" >
+          <van-loading />
+        </div>
       </template>
     </suspense>
-  </el-config-provider>
+  </van-config-provider>
 </template>
 
 <style>
@@ -36,8 +33,3 @@ body {
 }
 </style>
 
-<style scoped>
-.bg {
-  /* background-image: url('~/assets/bg.webp'); */
-}
-</style>

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

@@ -0,0 +1,98 @@
+<script setup>
+const props = defineProps({
+  url: {
+    type: String,
+    required: true,
+  },
+  d: {
+    type: Object,
+    required: false,
+  },
+})
+
+let page = 1
+
+let loading = $ref(false)
+let error = $ref(false)
+let finished = $ref(false)
+let refreshing = $ref(false)
+
+let list = $ref([])
+
+// request({
+//   url: props.url,
+//   data: {
+//     page,
+//     ...props.d
+//   },
+// })
+
+
+function onLoad() {
+  loading = true
+  request({
+    url: props.url,
+    data: {
+      page,
+      ...props.d
+    },
+  }).then(res => {
+    if (res.code === '1') {
+      if (refreshing) {
+        list = [];
+        refreshing = false;
+
+      }
+      list = list.concat(res.data.page_data)
+      loading = false
+      page++
+      if (res.data.page_now === res.data.total_page) {
+        finished = true
+      }
+    } else {
+      error = true
+    }
+
+  }).catch(err => {
+    console.log(err)
+  })
+
+}
+
+function onRefresh() {
+  finished = false
+  page = 1
+  refreshing = true
+  onLoad()
+}
+
+let timer;
+
+
+onBeforeUnmount(() => {
+  timer && clearInterval(timer)
+})
+
+watch(
+  () => props.d,
+  () => {
+    page = 1
+    refreshing = true
+    onLoad()
+  },
+  {
+    deep: true,
+  }
+)
+</script>
+
+<template>
+  <van-pull-refresh v-model="refreshing" @refresh="onRefresh">
+    <van-list v-model:loading="loading" v-model:error="error" error-text="请求失败,点击重新加载" :finished="finished"
+      finished-text="没有更多了" @load="onLoad" @click.stop>
+      <template v-for="item in list">
+        <slot :row="item"></slot>
+      </template>
+    </van-list>
+  </van-pull-refresh>
+</template>

+ 8 - 5
src/components/cuoti-detail/index.vue

@@ -1,4 +1,5 @@
 <script setup lang='ts'>
+import { showImagePreview } from 'vant';
 const props = defineProps<{
   d: any
 }>()
@@ -13,6 +14,7 @@ function translateString(str: string) {
 }
 
 function formatFileString(s: string) {
+  if(!s) return []
   return s.split(';').map((item) => window.GLOBAL_CONFIG.oss + item)
 }
 </script>
@@ -20,8 +22,8 @@ function formatFileString(s: string) {
 <template>
   <div class="space-y-4 mt-8">
     <div class="flex justify-between items-end">
-      <div class="text-xl whitespace-nowrap overflow-ellipsis overflow-hidden w-max-420px">{{ d.dc_title }}</div>
-      <el-tag>{{ d.dc_keyword }}</el-tag>
+      <div class="text-xl whitespace-nowrap overflow-ellipsis overflow-hidden w-max-320px">{{ d.dc_title }}</div>
+      <van-tag type="primary" size="large">{{ d.dc_keyword }}</van-tag>
     </div>
     <div class="flex space-x-6 text-gray-500">
       <div>{{ d.dc_grade_name }}</div>
@@ -32,9 +34,10 @@ function formatFileString(s: string) {
 
     <div class=" text-gray-600 pt-4" v-html="translateString(d.dc_content)"></div>
 
-    <div class="mt-6 flex flex-wrap items-start space-x-4">
-      <el-image fit="contain" class="w-1/6 mb-4" v-for="(src, idx) in formatFileString(d.dc_files)" :src="src"
-        :preview-src-list="formatFileString(d.dc_files)" :initial-index="idx" />
+    <div class="mt-6 grid grid-cols-2 gap-4">
+      <van-image fit="contain" v-for="(src, idx) in formatFileString(d.dc_files)" :src="src"
+        :preview-src-list="formatFileString(d.dc_files)" :initial-index="idx"
+        @click="showImagePreview({ images: formatFileString(d.dc_files), startPosition: idx })" />
     </div>
   </div>
 </template>

+ 60 - 0
src/components/multi-tree-select/index.vue

@@ -0,0 +1,60 @@
+<script setup lang='ts'>
+import { Grade, Subject } from '~/store/info'
+
+const emits = defineEmits(['confirm'])
+
+const Trees = [
+  {
+    text: '年级',
+    children: Grade.map(item => {
+      return {
+        text: item.grade_name,
+        id: 'g' + item.grade_id
+      }
+    })
+  },
+  {
+    text: '科目',
+    children: Subject.map(item => {
+      return {
+        text: item.subject_name,
+        id: 's' + item.subject_id
+      }
+    })
+  }
+
+]
+
+const showBottom = ref(false)
+
+const activeIndex = ref(0);
+const activeId = ref<string[]>([])
+
+function init() {
+  activeIndex.value = 0
+  activeId.value = []
+}
+
+function doConfirm() {
+  console.log('activeId : ', activeId)
+
+  emits('confirm', {
+    grade: activeId.value.filter(item => item[0] === 'g').map(item => item.slice(1)).join(','),
+    subject: activeId.value.filter(item => item[0] === 's').map(item => item.slice(1)).join(','),
+  })
+
+  showBottom.value = false
+}
+
+</script>
+
+<template>
+  <van-button type="primary" size="small" @click="showBottom = true">筛选</van-button>
+  <van-popup v-model:show="showBottom" round position="bottom" class="pt-4 px-4" @open="init">
+    <div class="flex justify-between mb-4">
+      <div @click="showBottom = false">取消</div>
+      <div @click="doConfirm" class="text-blue-400">确定</div>
+    </div>
+    <van-tree-select v-model:main-active-index="activeIndex" v-model:active-id="activeId" height="45vh" :items="Trees" />
+  </van-popup>
+</template>

+ 11 - 2
src/main.ts

@@ -4,7 +4,16 @@ import 'virtual:windi.css'
 import App from './App.vue'
 import router from './router/index'
 
-import "element-plus/theme-chalk/src/message.scss";
-import "element-plus/theme-chalk/src/message-box.scss";
+// import "element-plus/theme-chalk/src/message.scss";
+// import "element-plus/theme-chalk/src/message-box.scss";
+
+// Toast
+import 'vant/es/toast/style';
+// Dialog
+import 'vant/es/dialog/style';
+// Notify
+import 'vant/es/notify/style';
+// ImagePreview
+import 'vant/es/image-preview/style';
 
 createApp(App).use(router).mount('#appx')

+ 0 - 207
src/pages/admin/back/ctfx.vue

@@ -1,207 +0,0 @@
-<script setup lang='ts'>
-import { Search } from '@element-plus/icons-vue'
-import { useRouter, RouteLocationRaw } from 'vue-router'
-import { Grade, Subject, Status } from '~/store/info'
-import user from '~/store/user'
-
-const router = useRouter()
-function routerPush(_route: RouteLocationRaw) {
-  router.push(_route)
-}
-
-const tableData = ref([])
-const total = ref(0)
-const multipleSelection = ref([])
-const handleSelectionChange = (val) => {
-  multipleSelection.value = val
-}
-
-const queryForm = reactive({
-  dc_grade_id: undefined,
-  dc_subject_id: undefined,
-  dc_check: undefined,
-  dc_keyword: undefined,
-  page: 1
-})
-
-watch(queryForm, () => {
-  doQuery()
-}, { deep: true, immediate: true })
-
-function doQuery() {
-  request({
-    url: '/dyaw/ctfx/index',
-    data: {
-      ...queryForm,
-      // 管理员不需要传递sm_id
-      // sm_id: user.sm_info.sm_id,
-      // create_user_id: user.user_id
-    }
-  }).then(res => {
-    if (res.code === "1") {
-      tableData.value = res.data.page_data
-      total.value = parseInt(res.data.total_rows)
-    }
-  })
-}
-
-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()
-      }
-    }
-  )
-}
-
-
-function formatTime(s: string) {
-  return (new Date(s * 1000)).toLocaleString()
-}
-
-const dialogFormVisible = ref(false)
-const dialogForm = reactive({
-  dc_id: undefined,
-  dc_check: '1',
-  dc_check_desc: ''
-})
-function doJudge(id) {
-  // init doJudge
-  dialogForm.dc_id = id
-  dialogForm.dc_check = '1'
-  dialogForm.dc_check_desc = ''
-
-  dialogFormVisible.value = true
-}
-
-function doSubmit() {
-  request({
-    url: '/dyaw/ctfx/edit',
-    data: {
-      dc_id: dialogForm.dc_id,
-      dyaw_ctfx: {
-        dc_check: dialogForm.dc_check,
-        dc_check_desc: dialogForm.dc_check_desc,
-        dc_check_user_id: user.user_id
-      }
-    }
-  }).then(
-    res => {
-      if (res.code === "1") {
-        ElMessage.success('审核成功')
-        dialogFormVisible.value = false
-        doQuery()
-      }
-    }
-  )
-}
-
-</script>
-
-<template>
-  <div class="w-1400px h-640px flex flex-col">
-    <div class="flex justify-end 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>
-    </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" :disabled="row.dc_check !== '0'"
-              @click="doJudge(row.dc_id)">审核</el-button>
-            <el-button link type="primary" size="small"
-              @click="routerPush({ name: 'admin_back_ctfx_detail', 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>
-
-    <el-dialog v-model="dialogFormVisible" title="审核">
-      <el-form :model="dialogForm">
-        <el-form-item label="审核结果">
-          <el-radio-group v-model="dialogForm.dc_check">
-            <el-radio label="1">通过</el-radio>
-            <el-radio label="2">不通过</el-radio>
-          </el-radio-group>
-        </el-form-item>
-        <el-form-item label="处理意见" v-show="dialogForm.dc_check === '2'">
-          <el-input v-model="dialogForm.dc_check_desc" type="textarea" :rows="5" />
-        </el-form-item>
-      </el-form>
-      <template #footer>
-        <div class="w-full justify-end space-x-4">
-          <el-button @click="dialogFormVisible = false">取消</el-button>
-          <el-button type="primary" @click="doSubmit">
-            提交
-          </el-button>
-        </div>
-      </template>
-    </el-dialog>
-  </div>
-</template>
-
-
-<style scoped lang="scss">
-.tab_selected {
-  color: #007DFF;
-
-  &::after {
-    content: '-';
-    color: transparent;
-    position: absolute;
-    left: -5px;
-    right: -5px;
-    bottom: -4px;
-    height: 15px;
-    background: rgba(0, 125, 255, 0.30);
-    border-radius: 8px;
-  }
-}
-</style>

+ 0 - 52
src/pages/admin/back/ctfx/detail.vue

@@ -1,52 +0,0 @@
-<script setup lang='ts'>
-const router = useRouter()
-import { Status } from '~/store/info'
-
-const props = defineProps<{
-  id: string
-}>()
-
-const detail = ref(null)
-await request({
-  url: '/dyaw/ctfx/detail',
-  data: {
-    dc_id: props.id
-  }
-}).then(
-  res => {
-    if (res.code === "1") {
-      detail.value = res.data.one_info
-    }
-  }
-)
-</script>
-
-<template>
-  <div class="w-1400px h-640px flex flex-col">
-    <!-- <div class="flex justify-between">
-        <div class="space-x-2 text-blue-700 flex items-center">
-          <i:cil:home />
-          <span>首页</span>
-          <span>/</span>
-          <span>错题分析</span>
-          <span>/</span>
-          <span>上传错题</span>
-          <span>/</span>
-          <span class="text-gray-600">详情</span>
-        </div>
-        <el-button type="primary" @click="router.back()">返回</el-button>
-      </div> -->
-    <el-page-header @back="router.back()" content="错题详情" />
-    <el-divider />
-
-    <cuoti-detail v-if="detail" :d="detail" />
-
-    <el-divider />
-    <div>
-      <span>审核结果:</span><span class="text-gray-600">{{ Status[detail.dc_check] }}</span>
-    </div>
-    <div v-show="detail.dc_check === '2'">
-      <span>处理意见:</span><span class="text-gray-600">{{ detail.dc_check_desc }}</span>
-    </div>
-  </div>
-</template>

+ 29 - 0
src/pages/admin/container.vue

@@ -0,0 +1,29 @@
+<script setup lang='ts'>
+const tabs = [
+  { title: '错题列表', path: 'admin_index' },
+  { title: '错题审核', path: 'admin_indey' },
+]
+
+const route = useRoute()
+const active = ref(route.name)
+
+function onClickLeft() {
+  history.back()
+}
+</script>
+
+<template>
+  <div class="w-full h-screen flex flex-col">
+    <div class="w-full sticky top-0 z-100">
+      <slot name="nav">
+        <van-nav-bar title="错题分析" left-text="返回" left-arrow @click-left="onClickLeft" />
+      </slot>
+
+      <van-tabs v-model:active="active" class="sticky">
+        <van-tab v-for="tab in tabs" :title="tab.title" :name="tab.path" :to="{ name: tab.path }"></van-tab>
+      </van-tabs>
+    </div>
+
+    <slot :key="active" class="flex-auto"></slot>
+  </div>
+</template>

+ 62 - 82
src/pages/admin/index.vue

@@ -1,110 +1,90 @@
 <script setup lang='ts'>
-import { Search } from '@element-plus/icons-vue'
 import { useRouter, RouteLocationRaw } from 'vue-router'
-import { Grade, Subject } from '~/store/info'
-import user from '~/store/user'
+import tabContainer from './container.vue'
 
 const router = useRouter()
 function routerPush(_route: RouteLocationRaw) {
   router.push(_route)
 }
 
-const tableData = ref([])
-const total = ref(0)
+// const tableData = ref([])
+// const total = ref(0)
 
 const queryForm = reactive({
-  dc_grade_id: undefined,
-  dc_subject_id: undefined,
-  dc_keyword: undefined,
+  dc_grade_id: '',
+  dc_subject_id: '',
+  dc_keyword: '',
   page: 1
 })
 
-watch(queryForm, () => {
-  doQuery()
-}, { deep: true, immediate: true })
+// watch(queryForm, () => {
+//   doQuery()
+// }, { deep: true, immediate: true })
 
-function doQuery() {
-  request({
-    url: '/dyaw/ctfx/index',
-    data: {
-      ...queryForm,
-      // sm_id: user.sm_info.sm_id,
-      limit: 8,
-      dc_check: '1'
-    }
-  }).then(res => {
-    if (res.code === "1") {
-      tableData.value = res.data.page_data
-      total.value = parseInt(res.data.total_rows)
-    }
-  })
-}
+// function doQuery() {
+//   request({
+//     url: '/dyaw/ctfx/index',
+//     data: {
+//       ...queryForm,
+//       // sm_id: user.sm_info.sm_id,
+//       limit: 8,
+//       dc_check: '1'
+//     }
+//   }).then(res => {
+//     if (res.code === "1") {
+//       tableData.value = res.data.page_data
+//       total.value = parseInt(res.data.total_rows)
+//     }
+//   })
+// }
 
 // TODO: 临时处理
 function translateString(str: string) {
   return str
 }
+
+function getGradeAndSubject({ grade, subject }: { grade: string, subject: string }) {
+  console.log(grade, subject)
+  queryForm.dc_grade_id = grade
+  queryForm.dc_subject_id = subject
+}
 </script>
 
 <template>
-  <div class="w-1400px h-640px flex flex-col">
-    <div class="flex justify-between items-center">
-      <div class="flex flex-none space-x-12 text-lg h-50px">
-        <div class="cursor-pointer relative mb-22px tab_selected">错题列表</div>
-      </div>
-      <div class="flex space-x-2">
-        <el-select clearable size="large" placeholder="年级">
-          <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="科目">
-          <el-option v-for="({ subject_id, subject_name }) in Subject" :key="subject_id" :label="subject_name"
-            :value="subject_id" />
-        </el-select>
-        <el-input size="large" placeholder="关键字搜索" class="max-w-240px" :suffix-icon="Search"></el-input>
-      </div>
-    </div>
+  <tab-container>
 
-    <div class="flex-auto flex-col flex mt-4  justify-between">
-      <div class="grid grid-cols-2 grid-rows-4 gap-4">
-        <div class="cursor-pointer rounded shadow px-4 py-2 h-120px space-y-3" v-for="d in tableData"
-          @click="routerPush({ name: 'admin_index_detail', params: { id: d.dc_id } })">
-          <div class="flex justify-between">
-            <div class="text-xl whitespace-nowrap overflow-ellipsis overflow-hidden max-w-420px">{{ d.dc_title }}</div>
-            <el-tag>{{ d.dc_keyword }}</el-tag>
-          </div>
-          <div class="flex space-x-6 text-gray-500">
-            <div>{{ d.dc_grade_name }}</div>
-            <div>{{ d.dc_subject_name }}</div>
-          </div>
+    <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>
 
-          <div class="text-sm text-gray-500 whitespace-nowrap overflow-ellipsis overflow-hidden">{{
-            translateString(d.dc_content) }}</div>
+    <remote-list url="/dyaw/ctfx/index" :d="{
+      ...queryForm,
+      // sm_id: user.sm_info.sm_id,
+      dc_check: '1'
+    }" class="mt-2 flex-auto">
+      <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"
+            @click="routerPush({ name: 'teacher_index_detail', params: { id: d.dc_id } })">
+            <div class="flex justify-between">
+              <div class="text-xl whitespace-nowrap overflow-ellipsis overflow-hidden max-w-200px">{{ d.dc_title }}</div>
+              <van-tag type="primary">{{ d.dc_keyword }}</van-tag>
+            </div>
+            <div class="flex space-x-6 text-gray-500">
+              <div>{{ d.dc_grade_name }}</div>
+              <div>{{ d.dc_subject_name }}</div>
+            </div>
 
-        </div>
-      </div>
-      <div class="flex justify-end">
-        <el-pagination background layout="prev, pager, next" :total="total"></el-pagination>
-      </div>
+            <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>
 
-    </div>
-  </div>
+  </tab-container>
 </template>
 
-
-<style scoped lang="scss">
-.tab_selected {
-  color: #007DFF;
-
-  &::after {
-    content: '-';
-    color: transparent;
-    position: absolute;
-    left: -5px;
-    right: -5px;
-    bottom: -4px;
-    height: 15px;
-    background: rgba(0, 125, 255, 0.30);
-    border-radius: 8px;
-  }
-}
-</style>

+ 1 - 1
src/pages/admin/index/detail.vue

@@ -22,7 +22,7 @@ await request({
 </script>
 
 <template>
-  <div class="w-1400px h-640px flex flex-col">
+  <div class="w-full h-full flex flex-col">
     <div class="flex justify-between">
       <div class="space-x-2 text-blue-700 flex items-center">
         <i:cil:home />

+ 122 - 0
src/pages/admin/indey.vue

@@ -0,0 +1,122 @@
+<script setup lang='ts'>
+import { Search } from '@element-plus/icons-vue'
+import { useRouter, RouteLocationRaw } from 'vue-router'
+import { Grade, Subject, Status } from '~/store/info'
+import user from '~/store/user'
+import tabContainer from './container.vue'
+
+
+const router = useRouter()
+function routerPush(_route: RouteLocationRaw) {
+  router.push(_route)
+}
+
+// const tableData = ref([])
+// const total = ref(0)
+
+const queryForm = reactive({
+  dc_grade_id: '',
+  dc_subject_id: '',
+  dc_check: '',
+  dc_keyword: '',
+  page: 1,
+})
+
+// watch(queryForm, () => {
+//   doQuery()
+// }, { deep: true, immediate: true })
+
+// function doQuery() {
+//   request({
+//     url: '/dyaw/ctfx/index',
+//     data: {
+//       ...queryForm,
+//       sm_id: user.sm_info.sm_id,
+//       create_user_id: user.user_id
+//     }
+//   }).then(res => {
+//     if (res.code === "1") {
+//       tableData.value = res.data.page_data
+//       total.value = parseInt(res.data.total_rows)
+//     }
+//   })
+// }
+
+// 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()
+//       }
+//     }
+//   )
+// }
+
+
+// TODO: 临时处理
+function translateString(str: string) {
+  return str
+}
+function onClickLeft() {
+  history.back()
+}
+
+function getGradeAndSubject({ grade, subject }: { grade: string, subject: string }) {
+  console.log(grade, subject)
+  queryForm.dc_grade_id = grade
+  queryForm.dc_subject_id = subject
+}
+
+</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"
+            @click="routerPush({ name: 'admin_indey_detail', params: { id: d.dc_id } })">
+            <div class="flex justify-between">
+              <div class="flex space-x-2">
+                <van-tag type="primary">{{ d.dc_keyword }}</van-tag>
+                <div class="text-xl whitespace-nowrap overflow-ellipsis overflow-hidden max-w-160px">{{ d.dc_title }}
+                </div>
+              </div>
+              <div :class="d.dc_check === '1' ? 'text-green-500' : d.dc_check === '2' ? 'text-red-500' : 'text-blue-500'">
+                {{ Status[d.dc_check] }}</div>
+            </div>
+            <div class="flex space-x-6 text-gray-500">
+              <div>{{ d.dc_grade_name }}</div>
+              <div>{{ d.dc_subject_name }}</div>
+            </div>
+
+            <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>
+</template>
+

+ 117 - 0
src/pages/admin/indey/detail.vue

@@ -0,0 +1,117 @@
+<script setup lang='ts'>
+import { showFailToast, showSuccessToast } from 'vant';
+import user from '~/store/user'
+
+const router = useRouter()
+import { Status } from '~/store/info'
+
+const props = defineProps<{
+  id: string
+}>()
+
+const detail = ref()
+await request({
+  url: '/dyaw/ctfx/detail',
+  data: {
+    dc_id: props.id
+  }
+}).then(
+  res => {
+    if (res.code === "1") {
+      detail.value = res.data.one_info
+    }
+  }
+)
+
+function onClickLeft() {
+  router.back()
+}
+
+const dialogFormVisible = ref(false)
+function onClickRight() {
+  if (detail.value?.dc_check === '0') {
+    dialogForm.dc_check = '1'
+    dialogForm.dc_check_desc = ''
+    dialogFormVisible.value = true
+  } else {
+    showFailToast('当前错题已被审核')
+  }
+}
+
+const dialogForm = reactive({
+  dc_check: '1',
+  dc_check_desc: ''
+})
+
+const rules = reactive({
+  dc_check: [{ required: true, message: '审核结果不能为空', }],
+  dc_check_desc: [{ required: true, message: '处理意见不能为空', }],
+})
+
+const submit_loading = ref(false)
+
+function submitForm() {
+  submit_loading.value = true
+  request({
+    url: '/dyaw/ctfx/edit',
+    data: {
+      dc_id: props.id,
+      dyaw_ctfx: {
+        dc_check: dialogForm.dc_check,
+        dc_check_desc: dialogForm.dc_check_desc,
+        dc_check_user_id: user.user_id
+      }
+    }
+  }).then(
+    res => {
+      if (res.code === "1") {
+        detail.value = Object.assign(detail.value, dialogForm)
+        submit_loading.value = false
+        dialogFormVisible.value = false
+        showSuccessToast('审核成功')
+      }
+    }
+  )
+}
+</script>
+
+<template>
+  <div class="w-full h-full flex flex-col">
+    <van-nav-bar title="错题详情" left-text="返回" right-text="审核" left-arrow @click-left="onClickLeft"
+      @click-right="onClickRight" />
+    <div class="px-2">
+      <cuoti-detail v-if="detail" :d="detail" />
+
+      <van-divider />
+      <div>
+        <span>审核结果:</span><span class="text-gray-600">{{ Status[detail.dc_check] }}</span>
+      </div>
+      <div v-show="detail.dc_check === '2'">
+        <span>处理意见:</span><span class="text-gray-600">{{ detail.dc_check_desc }}</span>
+      </div>
+    </div>
+
+    <van-dialog v-model:show="dialogFormVisible" title="审核" :show-confirm-button="false">
+      <van-form @submit="submitForm" class="p-2">
+        <van-cell-group>
+          <van-field label="审核结果" prop="dc_title" :rules="rules.dc_check" required>
+            <template #input>
+              <van-radio-group v-model="dialogForm.dc_check" direction="horizontal">
+                <van-radio name="1" icon-size="16px">通过</van-radio>
+                <van-radio name="2" icon-size="16px">不通过</van-radio>
+              </van-radio-group>
+            </template>
+          </van-field>
+          <van-field label="处理意见" v-show="dialogForm.dc_check === '2'" prop="dc_check_desc" required
+            v-model="dialogForm.dc_check_desc" rows="3" autosize type="textarea">
+          </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>
+    </van-dialog>
+  </div>
+</template>

+ 65 - 77
src/pages/student/index.vue

@@ -9,102 +9,90 @@ function routerPush(_route: RouteLocationRaw) {
   router.push(_route)
 }
 
-const tableData = ref([])
-const total = ref(0)
+// const tableData = ref([])
+// const total = ref(0)
 
 const queryForm = reactive({
-  dc_grade_id: undefined,
-  dc_subject_id: undefined,
-  dc_keyword: undefined,
+  dc_grade_id: '',
+  dc_subject_id: '',
+  dc_keyword: '',
   page: 1
 })
 
-watch(queryForm, () => {
-  doQuery()
-}, { deep: true, immediate: true })
+// watch(queryForm, () => {
+//   doQuery()
+// }, { deep: true, immediate: true })
 
-function doQuery() {
-  request({
-    url: '/dyaw/ctfx/index',
-    data: {
-      ...queryForm,
-      sm_id: user.sm_info.sm_id,
-      limit: 8,
-      dc_check: '1'
-    }
-  }).then(res => {
-    if (res.code === "1") {
-      tableData.value = res.data.page_data
-      total.value = parseInt(res.data.total_rows)
-    }
-  })
-}
+// function doQuery() {
+//   request({
+//     url: '/dyaw/ctfx/index',
+//     data: {
+//       ...queryForm,
+//       sm_id: user.sm_info.sm_id,
+//       limit: 8,
+//       dc_check: '1'
+//     }
+//   }).then(res => {
+//     if (res.code === "1") {
+//       tableData.value = res.data.page_data
+//       total.value = parseInt(res.data.total_rows)
+//     }
+//   })
+// }
 
 // TODO: 临时处理
 function translateString(str: string) {
   return str
 }
+
+function onClickLeft() {
+  history.back()
+}
+
+function getGradeAndSubject({ grade, subject }: { grade: string, subject: string }) {
+  console.log(grade, subject)
+  queryForm.dc_grade_id = grade
+  queryForm.dc_subject_id = subject
+}
 </script>
 
 <template>
-  <div class="w-1400px h-640px flex flex-col">
-    <div class="flex justify-between items-center">
-      <div class="flex flex-none space-x-12 text-lg h-50px">
-        <div class="cursor-pointer relative mb-22px tab_selected">错题列表</div>
-      </div>
-      <div class="flex space-x-2">
-        <el-select clearable size="large" placeholder="年级">
-          <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="科目">
-          <el-option v-for="({ subject_id, subject_name }) in Subject" :key="subject_id" :label="subject_name"
-            :value="subject_id" />
-        </el-select>
-        <el-input size="large" placeholder="关键字搜索" class="max-w-240px" :suffix-icon="Search"></el-input>
+  <div class="w-full h-full flex flex-col">
+    <div class="w-full sticky top-0 z-100"><van-nav-bar title="错题分析" left-text="返回" left-arrow
+        @click-left="onClickLeft" />
+      <div class="flex justify-between items-center  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>
     </div>
 
-    <div class="flex-auto flex-col flex mt-4  justify-between">
-      <div class="grid grid-cols-2 grid-rows-4 gap-4">
-        <div class="cursor-pointer rounded shadow px-4 py-2 h-120px space-y-3" v-for="d in tableData"
-          @click="routerPush({ name: 'student_index_detail', params: { id: d.dc_id } })">
-          <div class="flex justify-between">
-            <div class="text-xl whitespace-nowrap overflow-ellipsis overflow-hidden max-w-420px">{{ d.dc_title }}</div>
-            <el-tag>{{ d.dc_keyword }}</el-tag>
-          </div>
-          <div class="flex space-x-6 text-gray-500">
-            <div>{{ d.dc_grade_name }}</div>
-            <div>{{ d.dc_subject_name }}</div>
-          </div>
-
-          <div class="text-sm text-gray-500 whitespace-nowrap overflow-ellipsis overflow-hidden">{{
-            translateString(d.dc_content) }}</div>
-
-        </div>
-      </div>
-      <div class="flex justify-end">
-        <el-pagination background layout="prev, pager, next" :total="total"></el-pagination>
-      </div>
+    <remote-list url="/dyaw/ctfx/index" :d="{
+      ...queryForm,
+      sm_id: user.sm_info.sm_id,
+      dc_check: '1'
+    }" class="mt-2 flex-auto">
+      <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"
+            @click="routerPush({ name: 'teacher_index_detail', params: { id: d.dc_id } })">
+            <div class="flex justify-between">
+              <div class="text-xl whitespace-nowrap overflow-ellipsis overflow-hidden max-w-200px">{{ d.dc_title }}</div>
+              <van-tag type="primary">{{ d.dc_keyword }}</van-tag>
+            </div>
+            <div class="flex space-x-6 text-gray-500">
+              <div>{{ d.dc_grade_name }}</div>
+              <div>{{ d.dc_subject_name }}</div>
+            </div>
 
-    </div>
+            <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>
   </div>
 </template>
 
 
-<style scoped lang="scss">
-.tab_selected {
-  color: #007DFF;
-
-  &::after {
-    content: '-';
-    color: transparent;
-    position: absolute;
-    left: -5px;
-    right: -5px;
-    bottom: -4px;
-    height: 15px;
-    background: rgba(0, 125, 255, 0.30);
-    border-radius: 8px;
-  }
-}
-</style>

+ 1 - 1
src/pages/student/index/detail.vue

@@ -22,7 +22,7 @@ await request({
 </script>
 
 <template>
-  <div class="w-1400px h-640px flex flex-col">
+  <div class="w-full h-full flex flex-col">
     <div class="flex justify-between">
       <div class="space-x-2 text-blue-700 flex items-center">
         <i:cil:home />

+ 29 - 0
src/pages/teacher/container.vue

@@ -0,0 +1,29 @@
+<script setup lang='ts'>
+const tabs = [
+  { title: '错题列表', path: 'teacher_index' },
+  { title: '上传错题', path: 'teacher_indey' },
+]
+
+const route = useRoute()
+const active = ref(route.name)
+
+function onClickLeft() {
+  history.back()
+}
+</script>
+
+<template>
+  <div class="w-full h-screen flex flex-col">
+    <div class="w-full sticky top-0 z-100">
+      <slot name="nav">
+        <van-nav-bar title="错题分析" left-text="返回" left-arrow @click-left="onClickLeft" />
+      </slot>
+
+      <van-tabs v-model:active="active" class="sticky">
+        <van-tab v-for="tab in tabs" :title="tab.title" :name="tab.path" :to="{ name: tab.path }"></van-tab>
+      </van-tabs>
+    </div>
+
+    <slot :key="active" class="flex-auto"></slot>
+  </div>
+</template>

+ 64 - 85
src/pages/teacher/index.vue

@@ -1,114 +1,93 @@
 <script setup lang='ts'>
-import { Search } from '@element-plus/icons-vue'
 import { useRouter, RouteLocationRaw } from 'vue-router'
-import { Grade, Subject } from '~/store/info'
 import user from '~/store/user'
+import tabContainer from './container.vue'
+
 
-const list = [
-  { title: '错题列表', route: '/' },
-]
 const router = useRouter()
 function routerPush(_route: RouteLocationRaw) {
   router.push(_route)
 }
 
-const tableData = ref([])
-const total = ref(0)
+// const tableData = ref<any[]>([])
+// const total = ref(0)
 
 const queryForm = reactive({
-  dc_grade_id: undefined,
-  dc_subject_id: undefined,
-  dc_keyword: undefined,
+  dc_grade_id: '',
+  dc_subject_id: '',
+  dc_keyword: '',
   page: 1
 })
 
-watch(queryForm, () => {
-  doQuery()
-}, { deep: true, immediate: true })
+// watch(queryForm, () => {
+//   doQuery()
+// }, { deep: true, immediate: true })
 
-function doQuery() {
-  request({
-    url: '/dyaw/ctfx/index',
-    data: {
-      ...queryForm,
-      sm_id: user.sm_info.sm_id,
-      limit: 8,
-      dc_check: '1'
-    }
-  }).then(res => {
-    if (res.code === "1") {
-      tableData.value = res.data.page_data
-      total.value = parseInt(res.data.total_rows)
-    }
-  })
-}
+// function doQuery() {
+//   request({
+//     url: '/dyaw/ctfx/index',
+//     data: {
+//       ...queryForm,
+//       sm_id: user.sm_info.sm_id,
+//       limit: 8,
+//       dc_check: '1'
+//     }
+//   }).then(res => {
+//     if (res.code === "1") {
+//       tableData.value = res.data.page_data
+//       total.value = parseInt(res.data.total_rows)
+//     }
+//   })
+// }
 
 // TODO: 临时处理
 function translateString(str: string) {
   return str
 }
+
+function getGradeAndSubject({ grade, subject }: { grade: string, subject: string }) {
+  console.log(grade, subject)
+  queryForm.dc_grade_id = grade
+  queryForm.dc_subject_id = subject
+}
+
 </script>
 
 <template>
-  <div class="w-1400px h-640px flex flex-col">
-    <div class="flex justify-between items-center">
-      <div class="flex flex-none space-x-12 text-lg h-50px">
-        <div class="cursor-pointer relative mb-22px tab_selected">错题列表</div>
-        <div class="cursor-pointer relative mb-22px" @click="routerPush({ name: 'teacher_indey' })">上传错题</div>
-      </div>
-      <div class="flex space-x-2">
-        <el-select clearable size="large" placeholder="年级">
-          <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="科目">
-          <el-option v-for="({ subject_id, subject_name }) in Subject" :key="subject_id" :label="subject_name"
-            :value="subject_id" />
-        </el-select>
-        <el-input size="large" placeholder="关键字搜索" class="max-w-240px" :suffix-icon="Search"></el-input>
-      </div>
-    </div>
+  <tab-container>
 
-    <div class="flex-auto flex-col flex mt-4  justify-between">
-      <div class="grid grid-cols-2 grid-rows-4 gap-4">
-        <div class="cursor-pointer rounded shadow px-4 py-2 h-120px space-y-3" v-for="d in tableData"
-          @click="routerPush({ name: 'teacher_index_detail', params: { id: d.dc_id } })">
-          <div class="flex justify-between">
-            <div class="text-xl whitespace-nowrap overflow-ellipsis overflow-hidden max-w-420px">{{ d.dc_title }}</div>
-            <el-tag>{{ d.dc_keyword }}</el-tag>
-          </div>
-          <div class="flex space-x-6 text-gray-500">
-            <div>{{ d.dc_grade_name }}</div>
-            <div>{{ d.dc_subject_name }}</div>
-          </div>
+    <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>
 
-          <div class="text-sm text-gray-500 whitespace-nowrap overflow-ellipsis overflow-hidden">{{
-            translateString(d.dc_content) }}</div>
+    <remote-list url="/dyaw/ctfx/index" :d="{
+      ...queryForm,
+      sm_id: user.sm_info.sm_id,
+      dc_check: '1'
+    }" class="mt-2 flex-auto">
+      <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"
+            @click="routerPush({ name: 'teacher_index_detail', params: { id: d.dc_id } })">
+            <div class="flex justify-between">
+              <div class="text-xl whitespace-nowrap overflow-ellipsis overflow-hidden max-w-200px">{{ d.dc_title }}</div>
+              <van-tag type="primary">{{ d.dc_keyword }}</van-tag>
+            </div>
+            <div class="flex space-x-6 text-gray-500">
+              <div>{{ d.dc_grade_name }}</div>
+              <div>{{ d.dc_subject_name }}</div>
+            </div>
 
-        </div>
-      </div>
-      <div class="flex justify-end">
-        <el-pagination background layout="prev, pager, next" :total="total"></el-pagination>
-      </div>
+            <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>
 
-    </div>
-  </div>
+  </tab-container>
 </template>
 
-
-<style scoped lang="scss">
-.tab_selected {
-  color: #007DFF;
-
-  &::after {
-    content: '-';
-    color: transparent;
-    position: absolute;
-    left: -5px;
-    right: -5px;
-    bottom: -4px;
-    height: 15px;
-    background: rgba(0, 125, 255, 0.30);
-    border-radius: 8px;
-  }
-}
-</style>

+ 20 - 17
src/pages/teacher/index/detail.vue

@@ -19,25 +19,28 @@ await request({
     }
   }
 )
+
+function onClickLeft() {
+  router.back()
+}
 </script>
 
 <template>
-  <div class="w-1400px h-640px flex flex-col">
-    <div class="flex justify-between">
-      <div class="space-x-2 text-blue-700 flex items-center">
-        <i:cil:home />
-        <span>首页</span>
-        <span>/</span>
-        <span>错题分析</span>
-        <span>/</span>
-        <span>错题列表</span>
-        <span>/</span>
-        <span class="text-gray-600">详情</span>
-      </div>
-      <el-button type="primary" @click="router.back()">返回</el-button>
-    </div>
-
-
-    <cuoti-detail v-if="detail" :d="detail" />
+  <div class="w-full h-full flex flex-col">
+    <!-- <div class="flex justify-between">
+        <div class="space-x-2 text-blue-700 flex items-center">
+          <i:cil:home />
+          <span>首页</span>
+          <span>/</span>
+          <span>错题分析</span>
+          <span>/</span>
+          <span>错题列表</span>
+          <span>/</span>
+          <span class="text-gray-600">详情</span>
+        </div>
+        <el-button type="primary" @click="router.back()">返回</el-button>
+      </div> -->
+    <van-nav-bar title="错题详情" left-text="返回" left-arrow @click-left="onClickLeft" />
+    <cuoti-detail v-if="detail" :d="detail" class="px-2" />
   </div>
 </template>

+ 157 - 109
src/pages/teacher/indey.vue

@@ -3,136 +3,184 @@ import { Search } from '@element-plus/icons-vue'
 import { useRouter, RouteLocationRaw } from 'vue-router'
 import { Grade, Subject, Status } from '~/store/info'
 import user from '~/store/user'
+import tabContainer from './container.vue'
+
 
-const list = [
-  { title: '错题列表', route: '/' },
-]
 const router = useRouter()
 function routerPush(_route: RouteLocationRaw) {
   router.push(_route)
 }
 
-const tableData = ref([])
-const total = ref(0)
-const multipleSelection = ref([])
-const handleSelectionChange = (val) => {
-  multipleSelection.value = val
-}
+// const tableData = ref([])
+// const total = ref(0)
 
 const queryForm = reactive({
-  dc_grade_id: undefined,
-  dc_subject_id: undefined,
-  dc_check: undefined,
-  dc_keyword: undefined,
-  page: 1
+  dc_grade_id: '',
+  dc_subject_id: '',
+  dc_check: '',
+  dc_keyword: '',
+  page: 1,
 })
 
-watch(queryForm, () => {
-  doQuery()
-}, { deep: true, immediate: true })
-
-function doQuery() {
-  request({
-    url: '/dyaw/ctfx/index',
-    data: {
-      ...queryForm,
-      sm_id: user.sm_info.sm_id,
-      create_user_id: user.user_id
-    }
-  }).then(res => {
-    if (res.code === "1") {
-      tableData.value = res.data.page_data
-      total.value = parseInt(res.data.total_rows)
-    }
-  })
-}
+// watch(queryForm, () => {
+//   doQuery()
+// }, { deep: true, immediate: true })
 
-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()
-      }
-    }
-  )
-}
+// function doQuery() {
+//   request({
+//     url: '/dyaw/ctfx/index',
+//     data: {
+//       ...queryForm,
+//       sm_id: user.sm_info.sm_id,
+//       create_user_id: user.user_id
+//     }
+//   }).then(res => {
+//     if (res.code === "1") {
+//       tableData.value = res.data.page_data
+//       total.value = parseInt(res.data.total_rows)
+//     }
+//   })
+// }
 
+// 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()
+//       }
+//     }
+//   )
+// }
+
+
+// TODO: 临时处理
+function translateString(str: string) {
+  return str
+}
+function onClickLeft() {
+  history.back()
+}
+function onClickRight() {
+  routerPush({ name: 'teacher_indey_create' })
+}
 
-function formatTime(s: string) {
-  return (new Date(s * 1000)).toLocaleString()
+function getGradeAndSubject({ grade, subject }: { grade: string, subject: string }) {
+  console.log(grade, subject)
+  queryForm.dc_grade_id = grade
+  queryForm.dc_subject_id = subject
 }
 
 </script>
 
 <template>
-  <div class="w-1400px h-640px flex flex-col">
-    <div class="flex justify-between items-center">
-      <div class="flex flex-none space-x-12 text-lg h-50px">
-        <div class="cursor-pointer relative mb-22px" @click="routerPush({ name: 'teacher_index' })">错题列表</div>
-        <div class="cursor-pointer relative mb-22px tab_selected">上传错题</div>
-      </div>
-      <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>
-    </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>
+  <tab-container>
+  <template #nav>
+    <van-nav-bar title="错题分析" left-text="返回" right-text="新建" left-arrow @click-left="onClickLeft"
+      @click-right="onClickRight" />
+  </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,
+    sm_id: user.sm_info.sm_id,
+  }" 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"
+            @click="routerPush({ name: 'teacher_indey_detail', params: { id: d.dc_id } })">
+            <div class="flex justify-between">
+              <div class="flex space-x-2">
+                <van-tag type="primary">{{ d.dc_keyword }}</van-tag>
+                <div class="text-xl whitespace-nowrap overflow-ellipsis overflow-hidden max-w-160px">{{ d.dc_title }}
+                </div>
+              </div>
+              <div :class="d.dc_check === '1' ? 'text-green-500' : d.dc_check === '2' ? 'text-red-500' : 'text-blue-500'">
+                {{ Status[d.dc_check] }}</div>
+            </div>
+            <div class="flex space-x-6 text-gray-500">
+              <div>{{ d.dc_grade_name }}</div>
+              <div>{{ d.dc_subject_name }}</div>
+            </div>
+
+            <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>
+              </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>
+            </tab-container> -->
 </template>
 
 
-<style scoped lang="scss">
+<!-- <style scoped lang="scss">
 .tab_selected {
   color: #007DFF;
 
@@ -148,4 +196,4 @@ function formatTime(s: string) {
     border-radius: 8px;
   }
 }
-</style>
+</style> -->

+ 144 - 130
src/pages/teacher/indey/create.vue

@@ -1,164 +1,178 @@
 <script setup lang='ts'>
-import { useRouter, RouteLocationRaw } from 'vue-router'
-import type { FormInstance, FormRules } from 'element-plus'
+import { useRouter } from 'vue-router'
 import { ref, reactive } from 'vue'
-import { Plus } from '@element-plus/icons-vue'
 import { Grade, Subject } from '~/store/info'
 import user from '~/store/user'
-const token = user.token
-
-import type { UploadProps, UploadUserFile } from 'element-plus'
+import { REQUEST } from '~/utils/request'
+import { showSuccessToast, showFailToast } from 'vant';
 
 const router = useRouter()
-function routerPush(_route: RouteLocationRaw) {
-  router.push(_route)
-}
 
-const UploadAction = window.GLOBAL_CONFIG.oss + '/upload/main/file'
-function handleUploadSuccess(res: any, file: UploadUserFile, fileList: UploadUserFile[]) {
-  file.p_url = '/' + res.data.url
-}
 
-const ruleFormRef = ref<FormInstance>()
 const ruleForm = reactive({
   dc_title: '',
   dc_grade_id: '',
   dc_subject_id: '',
   dc_keyword: '',
   dc_content: '',
-  dc_files: [],
+  dc_files: '',
+  //
+  dc_grade_name: '',
+  dc_subject_name: '',
 })
 
-const rules = reactive<FormRules>({
-  dc_title: [{ required: true, message: '标题不能为空', trigger: 'blur', }],
-  dc_grade_id: [{ required: true, message: '年级不能为空', trigger: 'blur', }],
-  dc_subject_id: [{ required: true, message: '科目不能为空', trigger: 'blur', }],
-  dc_keyword: [{ required: true, message: '关键字不能为空', trigger: 'blur', }],
+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 (formEl: FormInstance | undefined) => {
-  console.log('ruleForm : ', ruleForm)
-  if (!formEl) return
-  await formEl.validate((valid, fields) => {
-    if (valid) {
-      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') {
-            ElMessage.success('添加成功')
-            router.back()
-          } else {
-            ElMessage.error(res.msg)
-          }
-        }
-      ).catch(
-        err => {
-          ElMessage.error(err)
-        }
-      ).finally(
-        () => {
-          submit_loading.value = 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)
         }
-      )
-    } else {
-      console.log('error submit!')
-    }
-  })
+      }
+    ).catch(
+      err => {
+        showFailToast(err)
+      }
+    ).finally(
+      () => {
+        submit_loading.value = false
+      }
+    )
 }
 
-const resetForm = (formEl: FormInstance | undefined) => {
-  if (!formEl) return
-  formEl.resetFields()
+
+function onClickLeft() {
+  router.back()
 }
 
-const options = Array.from({ length: 10 }).map((_, idx) => ({
-  value: `${idx + 1}`,
-  label: `${idx + 1}`,
-}))
+const showGradePicker = ref(false)
+const showSubjectPicker = ref(false)
 
-const dialogImageUrl = ref('')
-const dialogVisible = ref(false)
-const handlePictureCardPreview: UploadProps['onPreview'] = (uploadFile) => {
-  dialogImageUrl.value = uploadFile.url!
-  dialogVisible.value = true
+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
 }
 
-// TODO: 临时处理
-function translateString(str: string) {
-  return str.split('\n').map((item) => `<p>${item}</p>`).join('')
+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 = ''
+
+      // 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'
+      fileProxy.message = '上传失败'
+    }
+  }).catch((err) => {
+    console.error(err)
+    fileProxy.status = 'failed'
+    fileProxy.message = '上传失败'
+  })
 }
 </script>
 
 <template>
-  <div class="w-1400px h-640px flex flex-col">
-    <div class="flex justify-between">
-      <div class="space-x-2 text-blue-700 flex items-center">
-        <i:cil:home />
-        <span>首页</span>
-        <span>/</span>
-        <span>错题分析</span>
-        <span>/</span>
-        <span>上传错题</span>
-        <span>/</span>
-        <span class="text-gray-600">新建</span>
+  <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>
-      <el-button type="primary" @click="router.back()">返回</el-button>
-    </div>
-
-
-    <el-form class="mt-8" ref="ruleFormRef" :model="ruleForm" :rules="rules" label-width="120px" size="large" status-icon>
-      <el-form-item label="标题" prop="dc_title">
-        <el-input v-model="ruleForm.dc_title" maxlength="20" show-word-limit />
-      </el-form-item>
-      <el-form-item label="年级" prop="dc_grade_id">
-        <el-select clearable v-model="ruleForm.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-form-item>
-      <el-form-item label="科目" prop="dc_subject_id">
-        <el-select clearable v-model="ruleForm.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-form-item>
-      <el-form-item label="关键字" prop="dc_keyword">
-        <el-input v-model="ruleForm.dc_keyword" maxlength="10" show-word-limit />
-      </el-form-item>
-      <el-form-item label="内容" prop="dc_content">
-        <el-input v-model="ruleForm.dc_content" type="textarea" :autosize="{ minRows: 3, maxRows: 4 }" />
-      </el-form-item>
-      <el-form-item label="图片" prop="dc_files">
-        <el-upload v-model:file-list="ruleForm.dc_files" list-type="picture-card" :on-preview="handlePictureCardPreview"
-          :action="UploadAction" name="filedata" :data="{ token, site: 'dyaw', }" :on-success="handleUploadSuccess">
-          <el-icon>
-            <Plus />
-          </el-icon>
-        </el-upload>
-
-        <el-dialog v-model="dialogVisible">
-          <img w-full :src="dialogImageUrl" alt="Preview Image" />
-        </el-dialog>
-      </el-form-item>
-      <el-form-item>
-        <el-button type="primary" @click="submitForm(ruleFormRef)" :loading="submit_loading" >
-          完成
-        </el-button>
-        <el-button @click="resetForm(ruleFormRef)">重置</el-button>
-      </el-form-item>
-    </el-form>
+    </van-form>
   </div>
 </template>

+ 15 - 22
src/pages/teacher/indey/detail.vue

@@ -19,33 +19,26 @@ await request({
     }
   }
 )
+
+function onClickLeft() {
+  router.back()
+}
 </script>
 
 <template>
-  <div class="w-1400px h-640px flex flex-col">
-    <div class="flex justify-between">
-      <div class="space-x-2 text-blue-700 flex items-center">
-        <i:cil:home />
-        <span>首页</span>
-        <span>/</span>
-        <span>错题分析</span>
-        <span>/</span>
-        <span>上传错题</span>
-        <span>/</span>
-        <span class="text-gray-600">详情</span>
+  <div class="w-full h-full flex flex-col">
+    <van-nav-bar title="错题详情" left-text="返回" left-arrow @click-left="onClickLeft" />
+    <div class="px-2">
+      <cuoti-detail v-if="detail" :d="detail" />
+
+      <van-divider />
+      <div>
+        <span>审核结果:</span><span class="text-gray-600">{{ Status[detail.dc_check] }}</span>
+      </div>
+      <div v-show="detail.dc_check === '2'">
+        <span>处理意见:</span><span class="text-gray-600">{{ detail.dc_check_desc }}</span>
       </div>
-      <el-button type="primary" @click="router.back()">返回</el-button>
     </div>
 
-
-    <cuoti-detail v-if="detail" :d="detail" />
-
-    <el-divider />
-    <div>
-      <span>审核结果:</span><span class="text-gray-600" >{{ Status[detail.dc_check] }}</span>
-    </div>
-    <div v-show="detail.dc_check === '2'">
-      <span>处理意见:</span><span class="text-gray-600">{{ detail.dc_check_desc }}</span>
-    </div>
   </div>
 </template>

+ 1 - 1
src/pages/teacher/indey/edit.vue

@@ -135,7 +135,7 @@ function translateString(str: string) {
 </script>
 
 <template>
-  <div class="w-1400px h-640px flex flex-col">
+  <div class="w-full h-full flex flex-col">
     <div class="flex justify-between">
       <div class="space-x-2 text-blue-700 flex items-center">
         <i:cil:home />

+ 32 - 16
src/router/routes/admin.ts

@@ -18,25 +18,41 @@ export default {
       ]
     },
     {
-      path: 'back',
+      path: 'indey',
       children: [
         {
-          path: 'ctfx',
-          children: [
-            {
-              path: '',
-              name: 'admin_back_ctfx',
-              component: () => import('~/pages/admin/back/ctfx.vue')
-            },
-            {
-              path: 'detail/:id',
-              name: 'admin_back_ctfx_detail',
-              component: () => import('~/pages/admin/back/ctfx/detail.vue'),
-              props: true
-            }
-          ]
+          path: '',
+          name: 'admin_indey',
+          component: () => import('~/pages/admin/indey.vue')
+        },
+        {
+          path: 'detail/:id',
+          name: 'admin_indey_detail',
+          component: () => import('~/pages/admin/indey/detail.vue'),
+          props: true
         },
       ]
-    }
+    },
+    // {
+    //   path: 'back',
+    //   children: [
+    //     {
+    //       path: 'ctfx',
+    //       children: [
+    //         {
+    //           path: '',
+    //           name: 'admin_back_ctfx',
+    //           component: () => import('~/pages/admin/back/ctfx.vue')
+    //         },
+    //         {
+    //           path: 'detail/:id',
+    //           name: 'admin_back_ctfx_detail',
+    //           component: () => import('~/pages/admin/back/ctfx/detail.vue'),
+    //           props: true
+    //         }
+    //       ]
+    //     },
+    //   ]
+    // }
   ]
 }

File diff suppressed because it is too large
+ 1 - 0
src/store/user.store.ts


+ 3 - 2
src/utils/request.ts

@@ -1,6 +1,7 @@
 import axios from 'axios'
 import type { AxiosRequestConfig } from 'axios'
-import { ElMessage } from 'element-plus'
+// import { ElMessage } from 'element-plus'
+import { showFailToast } from 'vant';
 import user from '~/store/user'
 const token = user.token
 
@@ -51,7 +52,7 @@ instance.interceptors.response.use(
     response.data.msg = response.data.msg.replaceAll(/<.*?>/g, ' ')
     const { code, msg } = response.data
     if (code !== '1')
-      ElMessage.error(msg)
+      showFailToast(msg)
 
     return response.data
   },

+ 8 - 8
vite.config.ts

@@ -4,7 +4,7 @@ import vue from '@vitejs/plugin-vue'
 import WindiCss from 'vite-plugin-windicss'
 import AutoImport from 'unplugin-auto-import/vite'
 import Components from 'unplugin-vue-components/vite'
-import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
+import { VantResolver } from 'unplugin-vue-components/resolvers'
 import Icons from 'unplugin-icons/vite'
 import IconsResolver from 'unplugin-icons/resolver'
 import ConditionalCompile from './plugins/vite-plugin-conditional-compile'
@@ -31,11 +31,11 @@ export default defineConfig({
     },
   },
   css: {
-    preprocessorOptions: {
-      scss: {
-        additionalData: '@use "./element.scss" as *;',
-      },
-    },
+    // preprocessorOptions: {
+    //   scss: {
+    //     additionalData: '@use "./element.scss" as *;',
+    //   },
+    // },
   },
   plugins: [
     ConditionalCompile(),
@@ -51,7 +51,7 @@ export default defineConfig({
         // 'src/store',
         'src/utils',
       ],
-      resolvers: [ElementPlusResolver()],
+      resolvers: [VantResolver()],
       vueTemplate: true,
       eslintrc: {
         enabled: true,
@@ -67,7 +67,7 @@ export default defineConfig({
       extensions: ['vue', 'md'],
       // allow auto import and register components used in markdown
       include: [/\.vue$/, /\.vue\?vue/, /\.md$/],
-      resolvers: [ElementPlusResolver({ importStyle: 'sass' }), IconsResolver()],
+      resolvers: [VantResolver(), IconsResolver()],
     }),
     Icons({
       compiler: 'vue3',

File diff suppressed because it is too large
+ 0 - 121
vite.config.ts.js