From 5f00696dfb25bc90034448ceb634ed1ef256681a Mon Sep 17 00:00:00 2001
From: qiyunfeng-create <1940665526@qq.com>
Date: 星期四, 21 八月 2025 21:13:35 +0800
Subject: [PATCH] Merge branch 'master' of http://182.92.203.7:2001/r/xiehe_website

---
 src/views/courseManage/components/class.vue |  502 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 502 insertions(+), 0 deletions(-)

diff --git a/src/views/courseManage/components/class.vue b/src/views/courseManage/components/class.vue
new file mode 100644
index 0000000..442fd27
--- /dev/null
+++ b/src/views/courseManage/components/class.vue
@@ -0,0 +1,502 @@
+<template>
+  <div class="classPage">
+    <div class="headerBox">
+      <div class="searchBox">
+        <el-input v-model="searchKey" @clear="searchData()" clearable placeholder="璇疯緭鍏ュ叧閿瓧">
+          <template #append>
+            <el-button type="primary" class="searchBtn" :icon="Search" @click="searchData()" />
+          </template>
+        </el-input>
+      </div>
+      <el-button type="primary" class="applyStartClasses" @click="applyClass">鐢宠寮�鐝�</el-button>
+    </div>
+    <div class="classListBox" v-loading="pages.loading">
+      <div class="classItem" v-for="(item, index) in classList" :key="index">
+        <div class="itemHeader">
+          <div class="title">{{ item.name }}</div>
+          <div class="classId">锛圛D锛歿{ item.id }}锛�</div>
+          <div class="copyIdBtn" v-if="item.applyState == 'Normal'" @click="copy(item.refCode)">
+            澶嶅埗閭�璇风爜
+          </div>
+          <div
+            class="copyIdBtn"
+            style="background: transparent; padding: 0"
+            v-if="item.applyState == 'Reject'"
+          >
+            <el-icon @click="delClass(item)" style="color: red; font-size: 14px"
+              ><Delete
+            /></el-icon>
+          </div>
+        </div>
+        <div class="itemInfo" @click="groupDetail(item)">
+          <div class="infoBox">
+            <p>
+              鐘舵�侊細<span v-if="item.applyState == 'WaitAudit'" style="color: #ef9f29">
+                瀹℃牳涓� </span
+              ><span v-if="item.applyState == 'Normal'" style="color: #1dbd11"> 杩涜涓� </span
+              ><span v-if="item.applyState == 'Reject'" style="color: red"> 鏈�氳繃 </span>
+            </p>
+            <p v-if="item.applyState == 'Reject'">
+              鎷掔粷鍘熷洜锛�<span style="color: red">{{ item.reason != '' ? item.reason : '-' }}</span>
+            </p>
+            <p>鐝骇浜烘暟锛歿{ item.memberCount }} / {{ item.maxUserCount }}</p>
+            <p>
+              鏈夋晥鏈燂細{{ moment(item.beginDate).format('YYYY-MM-DD') }} -
+              {{ moment(item.endDate).format('YYYY-MM-DD') }}
+            </p>
+          </div>
+        </div>
+      </div>
+    </div>
+    <div class="pagination-box" v-if="classList.length > 0">
+      <el-pagination
+        v-model:current-page="pages.page"
+        v-model:page-size="pages.pageSize"
+        :background="false"
+        layout="total, prev, pager, next"
+        :total="pages.count"
+        @current-change="pageChange"
+        @size-change="handleSizeChange"
+      />
+    </div>
+    <div class="nullBox" v-if="!pages.loading && classList.length == 0">
+      <el-empty />
+    </div>
+    <!-- 鐢宠寮�鐝脊妗� -->
+    <el-dialog v-model="applyClassDialog" width="450" align-center>
+      <template #title>鐢宠寮�鐝�</template>
+      <el-form :model="formData" label-position="left" ref="dialogFormRef" label-width="100px">
+        <el-form-item
+          label="鐝骇鍚嶇О"
+          prop="name"
+          :rules="[{ required: true, message: '璇疯緭鍏ョ彮绾у悕绉�' }]"
+        >
+          <el-input v-model="formData.name" placeholder="璇疯緭鍏ョ彮绾у悕绉�" />
+        </el-form-item>
+        <el-form-item
+          label="鐝骇浜烘暟"
+          prop="num"
+          :rules="[{ required: true, message: '璇疯緭鍏ョ彮绾т汉鏁�' }]"
+        >
+          <el-input-number v-model="formData.num" :min="1" :step="1" :precision="0" />
+        </el-form-item>
+        <el-form-item
+          label="鐝骇鏈夋晥鏈�"
+          prop="date"
+          :rules="[{ required: true, message: '璇烽�夋嫨鐝骇鏈夋晥鏈�' }]"
+        >
+          <el-date-picker
+            v-model="formData.date"
+            type="daterange"
+            range-separator="-"
+            start-placeholder="寮�濮嬫椂闂�"
+            end-placeholder="缁撴潫鏃堕棿"
+          />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="applyClassDialog = false">鍙栨秷</el-button>
+          <el-button type="primary" @click="submit" :loading="submitLoading">鎻愪氦</el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { defineProps, reactive, ref, onMounted, inject, watch } from 'vue'
+import { Search } from '@element-plus/icons-vue'
+import { ElMessage } from 'element-plus'
+import { getPublicImage } from '@/assets/js/middleGround/tool.js'
+import moment from 'moment'
+import { useRouter } from 'vue-router'
+import useClipboard from 'vue-clipboard3'
+
+const { toClipboard } = useClipboard()
+const uRouter = useRouter()
+const MG: any = inject('MG')
+const props = defineProps<{
+  courseId: number
+  bookInfo: any
+}>()
+
+const emit = defineEmits(['refreshParent'])
+
+// 鐢宠寮�鐝槻鎶杔oading
+const submitLoading = ref(false)
+
+const classList: any = ref([])
+
+onMounted(() => {
+  getData()
+})
+
+const searchKey = ref('')
+const pages = reactive({
+  page: 1,
+  pageSize: 6,
+  count: 0,
+  loading: true
+})
+
+const searchData = () => {
+  pages.page = 1
+  pages.pageSize = 10
+  getData()
+}
+
+// 鑾峰彇鐝骇
+const getData = () => {
+  pages.loading = true
+  MG.edu
+    .getCourseClassList({
+      courseId: props.courseId,
+      start: (pages.page - 1) * pages.pageSize,
+      size: pages.pageSize,
+      sort: {
+        type: 'Desc',
+        field: 'CreateDate'
+      },
+      filterList: [],
+      searchList: searchKey.value
+        ? [
+            {
+              keywords: searchKey.value,
+              field: 'Name',
+              compareType: 'Contains'
+            }
+          ]
+        : []
+    })
+    .then((res: any) => {
+      pages.loading = false
+      pages.count = res.totalSize;
+      classList.value = res.datas.map((item: any) => {
+        return {
+          ...item,
+          name: item.name,
+          id: item.id,
+          icon: item.icon ? getPublicImage(item.icon, 80) : '',
+          introduction: item.description,
+          reason: item.applyReturnMsg ? JSON.parse(item.applyReturnMsg).reason : ''
+        }
+      })
+      refreshParent()
+    })
+}
+
+// 鍔犲叆鐝骇
+const applyClass = () => {
+  formData.value = {
+    name: '',
+    num: '',
+    date: ''
+  }
+  applyClassDialog.value = true
+}
+
+// 鍒锋柊鐖剁粍浠舵暟鎹�
+const refreshParent = () => {
+  emit('refreshParent', 'del')
+}
+
+const applyClassDialog = ref(false)
+const formData = ref({
+  name: '',
+  num: '',
+  date: ''
+})
+
+const submit = () => {
+  submitLoading.value = true
+  MG.edu
+    .newCourseClass({
+      courseId: props.courseId,
+      name: formData.value.name,
+      description: '',
+      icon: '',
+      type: 'class',
+      beginDate: moment(formData.value.date[0]).format('YYYY-MM-DD'),
+      endDate: moment(formData.value.date[1]).format('YYYY-MM-DD'),
+      config: '',
+      price: 0,
+      maxUserCount: formData.value.num
+    })
+    .then((res: any) => {
+      if (res) {
+        setTimeout(() => {
+          submitLoading.value = false
+          ElMessage.success('寮�鐝凡鐢宠锛岀瓑寰呯鐞嗗憳瀹℃牳銆�')
+          applyClassDialog.value = false
+          getData()
+        }, 1000)
+      }
+    })
+    .catch((err: any) => {
+      ElMessage.error('寮�鐝敵璇峰嚭閿欙紝璇风◢鍚庡啀璇�')
+      setTimeout(() => {
+        submitLoading.value = false
+      }, 1000)
+    })
+}
+
+// 澶嶅埗
+const copy = async (text: string) => {
+  try {
+    await toClipboard(text)
+    ElMessage({
+      message: '澶嶅埗鎴愬姛',
+      type: 'success'
+    })
+  } catch (e) {
+    console.error(e)
+  }
+}
+
+// 鍒犻櫎鐝骇
+const delClass = (item: any) => {
+  const data = {
+    ids: [item.id]
+  }
+  MG.edu
+    .delCourseClass(data)
+    .then((res: any) => {
+      if (res) {
+        ElMessage({
+          message: '宸插垹闄�',
+          type: 'success'
+        })
+        getData()
+      }
+    })
+    .catch((err: any) => {
+      ElMessage({
+        message: '鍒犻櫎澶辫触',
+        type: 'error'
+      })
+      console.log(err)
+    })
+}
+
+// 鑾峰彇瀹℃牳閫氳繃鐨勮绋�
+const coursePages = reactive({
+  page: 1,
+  pageSize: 10,
+  count: 0,
+  loading: false
+})
+const courseListData = ref([])
+
+// const getCourse = () => {
+//   coursePages.loading = true
+//   const searchData = [
+//     {
+//       keywords: 'jsek_digitalTextbooks',
+//       field: 'ProductType'
+//     }
+//   ]
+//   const data = {
+//     Size: coursePages.pageSize,
+//     Start: coursePages.pageSize * coursePages.page - coursePages.pageSize,
+//     sort: {
+//       type: 'Desc',
+//       field: 'CreateDate'
+//     },
+//     searchList: searchData
+//   }
+//   MG.store
+//     .getPurchasedProductList(data)
+//     .then((res: any) => {
+//       coursePages.count = res.totalSize
+//       courseListData.value = res.datas.map((item: any) => {
+//         return {
+//           ...item,
+//           img: item.product.icon ? getPublicImage(item.product.icon, 80) : ''
+//         }
+//       })
+//       coursePages.loading = false
+//     })
+//     .catch(() => {
+//       coursePages.loading = false
+//     })
+// }
+
+const pageChange = (val: number) => {
+  pages.page = val
+  getData()
+}
+const handleSizeChange = (val: number) => {
+  pages.pageSize = val
+  getData()
+}
+
+const groupDetail = (item: any) => {
+  if (item.applyState == 'WaitAudit') {
+    ElMessage({
+      message: '姝e湪瀹℃牳涓�....',
+      type: 'warning'
+    })
+    return false
+  }
+  if (item.applyState == 'Reject') {
+    ElMessage({
+      message: '瀹℃牳鏈�氳繃',
+      type: 'warning'
+    })
+    return false
+  }
+  const bookData = item.linkProductDto.product
+  let classinfo: any = {
+    id: item.id,
+    name: item.name,
+    courseId: props.courseId,
+    icon: bookData.icon,
+    rootCmsItemId: bookData.rootCmsItemId,
+    bookId: bookData.id,
+    author: bookData.author,
+    isbn: bookData.isbn,
+    bookRefCode: bookData.refCode
+  }
+  let page = uRouter.resolve({
+    path: '/classManage',
+    query: {
+      classInfo: JSON.stringify(classinfo)
+    }
+  })
+  window.open(page.href, '_blank')
+}
+</script>
+
+<style lang="less" scoped>
+.classPage {
+  .headerBox {
+    margin-bottom: 10px;
+    overflow: hidden;
+    .searchBox {
+      width: 300px;
+      float: left;
+      .searchBtn {
+        background-color: var(--el-color-primary);
+        color: #fff;
+        border-top-left-radius: 0;
+        border-bottom-left-radius: 0;
+      }
+    }
+    .applyStartClasses {
+      float: right;
+    }
+  }
+  .classListBox {
+    overflow: hidden;
+    min-height: 200px;
+    .classItem {
+      float: left;
+      width: 49%;
+      margin-bottom: 16px;
+      margin-right: 1%;
+      border-radius: 8px;
+      border: 1px solid #efefef;
+      overflow: hidden;
+
+      &:nth-child(2n) {
+        margin-left: 1%;
+        margin-right: 0;
+      }
+      .itemHeader {
+        height: 40px;
+        line-height: 40px;
+        padding: 0 20px;
+        background-color: #f8f8f8;
+        div {
+          display: inline-block;
+        }
+        .classId {
+          margin-left: 6px;
+          font-size: 12px;
+          color: #999;
+        }
+        .copyIdBtn {
+          float: right;
+          height: 20px;
+          line-height: 20px;
+          margin-top: 10px;
+          font-size: 12px;
+          background-color: #fff;
+          color: #3b93fe;
+          padding: 0 6px;
+          border-radius: 50px;
+          overflow: hidden;
+          cursor: pointer;
+        }
+      }
+      .itemInfo {
+        height: 128px;
+        padding: 20px;
+        flex: 1;
+        display: flex;
+        cursor: pointer;
+        .infoBox {
+          flex: 1;
+          font-size: 12px;
+          p {
+            margin-bottom: 10px;
+          }
+        }
+      }
+    }
+  }
+}
+
+.courseList {
+  overflow: hidden;
+  margin-bottom: 20px;
+
+  .courseItem {
+    float: left;
+    width: 100px;
+    margin: 10px;
+    position: relative;
+
+    .checkBox {
+      position: absolute;
+      right: 0;
+      top: 0;
+      height: 14px;
+
+      ::v-deep {
+        .el-checkbox__inner {
+          border-color: #888;
+        }
+      }
+    }
+
+    .imgBox {
+      width: 100px;
+      height: 110px;
+      margin-bottom: 10px;
+    }
+
+    p {
+      line-height: 1.2;
+      display: -webkit-box;
+      -webkit-line-clamp: 2;
+      -webkit-box-orient: vertical;
+      overflow: hidden;
+    }
+  }
+}
+
+.pagination-box {
+  padding: 10px 0;
+  display: flex;
+  justify-content: center;
+}
+
+.nullBox {
+  text-align: center;
+  margin-top: 30px;
+  font-size: 20px;
+  color: #ccc;
+}
+</style>

--
Gitblit v1.9.1