<template>
  <div class="manage-list-remote">
    <div class="filter-wrapper">
      <div class="filter-row filter-row--primary">
        <div class="filter-fields">
          <div class="filter-field filter-field--name">
            <el-input type="text" placeholder="课程名称" v-model="params.name" clearable maxlength="50"></el-input>
          </div>
          <div class="filter-field filter-field--category">
            <el-cascader placeholder="课程分类" clearable v-model="sysTypeList" :props="defaultTypeProps"
              :options="sysTypeListMap"></el-cascader>
          </div>
          <div class="filter-field filter-field--teacher teacher-filter">
            <div class="teacher-select-wrapper">
              <el-select
                class="creator-select"
                ref="teacherSelect"
                v-model="teacherSelected"
                multiple
                filterable
                remote
                clearable
                reserve-keyword
                placeholder="授课教师"
                :multiple-limit="5"
                :remote-method="remoteSearchTeacher"
                :loading="teacherLoading"
                @input.native="limitTeacherInput"
                @visible-change="handleTeacherVisibleChange"
                @change="handleTeacherChange"
                @clear="handleTeacherClear"
              >
                <el-option v-for="item in teacherOptions" :key="item.teacherId" :label="item.teacherName"
                  :value="item.teacherId">
                  <span>{{ item.teacherName }}</span>
                  <span v-if="item.teacherCode" class="option-code">（{{ item.teacherCode }}）</span>
                </el-option>
              </el-select>
            </div>
          </div>
          <div class="filter-field filter-field--time learning-time-range">
            <div :class="[
              'grid-content',
              'bg-purple',
              'resetDatePicker',
              !learningTimeRange || learningTimeRange.length === 0 ? 'noSplitDatePicker' : ''
            ]">
              <el-date-picker v-model="learningTimeRange" type="daterange" align="right" unlink-panels clearable
                value-format="yyyy-MM-dd 00:00:00" range-separator="至" start-placeholder="培训时间"
                :picker-options="pickerOptions" @change="handleLearningTimeRangeChange"></el-date-picker>
            </div>
          </div>
          <div class="filter-field filter-field--status">
            <el-select v-model="params.status" placeholder="审核状态" clearable>
              <el-option label="-" value="1"></el-option>
              <el-option label="审核中" value="2"></el-option>
              <el-option label="审核通过" value="5"></el-option>
              <el-option label="审核驳回" value="3"></el-option>
            </el-select>
          </div>
          <div class="filter-field filter-field--publish">
            <el-select v-model="params.publish" placeholder="发布状态" clearable>
              <el-option label="已发布" :value="true"></el-option>
              <el-option label="未发布" :value="false"></el-option>
            </el-select>
          </div>

        </div>
        <div class="filter-actions" v-show="!showAdvancedFilter">
          <el-button type="text" class="toggle-link" @click="toggleAdvancedFilter">
            {{ showAdvancedFilter ? '收起' : '展开' }}
            <i :class="showAdvancedFilter ? 'el-icon-arrow-up' : 'el-icon-arrow-down'"></i>
          </el-button>
          <el-tooltip content="查询" placement="top" effect="dark" popper-class="icon-btn-tooltip">
            <div class="icon-btn icon-btn--search" @click="searchData(true)" aria-label="查询"></div>
          </el-tooltip>
          <el-tooltip content="重置" placement="top" effect="dark" popper-class="icon-btn-tooltip">
            <div class="icon-btn icon-btn--reset" @click="reset" aria-label="重置"></div>
          </el-tooltip>
        </div>
      </div>
      <div v-if="showAdvancedFilter" class="filter-row filter-row--advanced advanced-filter">
        <div class="filter-fields">
          <div class="filter-field filter-field--enabled">
            <el-select v-model="params.enabled" placeholder="启停用状态" clearable>
              <el-option label="启用" :value="true"></el-option>
              <el-option label="停用" :value="false"></el-option>
            </el-select>
          </div>
          <div class="filter-field filter-field--open">
            <el-select v-model="params.openCourse" placeholder="是否公开课" clearable>
              <el-option label="是" :value="1"></el-option>
              <el-option label="否" :value="0"></el-option>
            </el-select>
          </div>
          <div class="filter-field filter-field--resowner">
            <el-cascader
              ref="resOwnerCascader"
              v-model="resOwnerSelected"
              placeholder="资源归属"
              clearable
              :props="resOwnerCascaderProps"
              :options="resOwnerOptions"
              :show-all-levels="false"
              @change="handleResOwnerChange"
              @input.native="limitResOwnerInput"
              @clear="handleResOwnerClear"
              @visible-change="handleResOwnerVisibleChange"
              filterable
              :filter-method="resOwnerFilterMethod"
            ></el-cascader>
          </div>
          <div class="filter-field filter-field--creator creator-filter">
            <div class="teacher-select-wrapper">
              <el-select
                class="creator-select"
                ref="creatorSelect"
                v-model="creatorSelected"
                multiple
                filterable
                remote
                clearable
                reserve-keyword
                placeholder="创建人"
                :multiple-limit="5"
                :remote-method="remoteSearchCreator"
                :loading="creatorLoading"
                @input.native="limitCreatorInput"
                @visible-change="handleCreatorVisibleChange"
                @change="handleCreatorChange"
                @clear="handleCreatorClear"
              >
                <el-option v-for="item in creatorOptions" :key="item.userId" :label="item.name" :value="item.userId">
                  <span>{{ item.name }}</span>
                  <span v-if="item.code" class="option-code">（{{ item.code }}）</span>
                </el-option>
              </el-select>
            </div>
          </div>
          <div class="filter-field filter-field--create-from">
            <el-select v-model="params.createFrom" placeholder="创建来源" clearable>
              <el-option label="教师端" value="teacher"></el-option>
              <el-option label="管理端" value="admin"></el-option>
            </el-select>
          </div>
        </div>
        <div class="filter-actions filter-actions--inline">
          <el-button type="text" class="toggle-link" @click="toggleAdvancedFilter">
            {{ showAdvancedFilter ? '收起' : '展开' }}
            <i :class="showAdvancedFilter ? 'el-icon-arrow-up' : 'el-icon-arrow-down'"></i>
          </el-button>
          <el-tooltip content="查询" placement="top" effect="dark" popper-class="icon-btn-tooltip">
            <div class="icon-btn icon-btn--search" @click="searchData(true)" aria-label="查询"></div>
          </el-tooltip>
          <el-tooltip content="重置" placement="top" effect="dark" popper-class="icon-btn-tooltip">
            <div class="icon-btn icon-btn--reset" @click="reset" aria-label="重置"></div>
          </el-tooltip>
        </div>
      </div>

    </div>
    <div class="table-wrapper">
      <div class="filter-extra-actions">
        <div class="create-course-btn" @click="addNewCourse()" aria-label="新建课程">新建课程</div>
        <!-- AI 播放器相关：批量语种设置 / 开启AI处理 -->
        <el-button
          v-if="aiPermission"
          type="primary"
          @click="setLanguage()"
          icon="el-icon-connection"
          :disabled="selectedCourses.length === 0"
        >
          设置语种
        </el-button>
        <el-button
          v-if="aiPermission"
          type="primary"
          @click="enableAI()"
          icon="el-icon-switch-button"
          :disabled="selectedCourses.length === 0"
        >
          开启AI处理
        </el-button>
        <el-tooltip v-if="showSetTopFeature" content="置顶排序" placement="top" effect="dark" popper-class="icon-btn-tooltip">
          <div class="icon-btn icon-btn--top" @click="handleTopSort" aria-label="置顶排序"></div>
        </el-tooltip>
        <el-tooltip content="导出" placement="top" effect="dark" popper-class="icon-btn-tooltip">
          <div class="icon-btn icon-btn--export" :class="{ 'is-loading': exportLoading, 'is-disabled': exportLoading }"
            @click="!exportLoading && handleExport()" aria-label="导出"></div>
        </el-tooltip>
      </div>
      <el-table :data="pageData" @sort-change="handleSortChange" @selection-change="handleSelectionChange">
        <!-- AI 播放器相关：多选勾选列 -->
        <el-table-column v-if="aiPermission" type="selection" width="55"></el-table-column>
        <el-table-column v-if="forChoose" label="选择" width="80" align="center">
          <template slot-scope="scope" v-if="scope.row.published">
            <el-button type="default" size="mini" @click="handleChoose(scope.row)">选择</el-button>
          </template>
        </el-table-column>
        <el-table-column label="课程名称" prop="name" header-align="center" align="left" min-width="360"
          show-overflow-tooltip fixed="left" sortable="custom">
          <template slot-scope="scope">
            <span class="course-name" @click="viewTopic(scope.row)">{{ scope.row.name }}</span>
          </template>
        </el-table-column>
        <el-table-column label="课程分类" prop="sysType" min-width="180" align="center" sortable="custom" show-overflow-tooltip>
          <template slot-scope="scope">
            <span class="common-cell common-cell-right single-line-ellipsis">{{ formatSysTypeChain(scope.row) }}</span>
          </template>
        </el-table-column>
        <el-table-column label="授课教师" prop="teacherName" :min-width="teacherColumnWidth" align="center" >
          <template slot-scope="scope">
            <span class="common-cell">{{ scope.row.teacherName }}</span>
          </template>
        </el-table-column>
        <el-table-column label="课程时长" prop="courseDuration" min-width="110" align="center" sortable="custom">
          <template slot-scope="scope">
            <span class="common-cell common-cell-right">{{ formatCourseDuration(scope.row) }}</span>
          </template>
        </el-table-column>
        <el-table-column label="学习人数" prop="studys" min-width="110" align="center" sortable="custom">
          <template slot-scope="scope">
            <span class="common-cell common-cell-right">{{ scope.row.studys || '-' }}</span>
          </template>
        </el-table-column>
        <el-table-column label="课程评分" prop="score" min-width="110" align="center" sortable="custom">
          <template slot-scope="scope">
            <span class="common-cell common-cell-right">{{ formatScore(scope.row) }}</span>
          </template>
        </el-table-column>
        <el-table-column label="审核状态" prop="status" min-width="110" align="center" sortable="custom">
          <template slot-scope="scope">
            <span class="common-cell common-cell-right" v-if="scope.row.status == 1">-</span>
            <span :class="['common-cell common-cell-right', 'status--audit']" v-if="scope.row.status == 2">审核中</span>
            <span :class="['common-cell common-cell-right', 'status--pass']" v-if="scope.row.status == 5">审核通过</span>
            <span :class="['common-cell common-cell-right', 'status--reject']" v-if="scope.row.status == 3">审核驳回</span>
          </template>
        </el-table-column>
        <el-table-column label="发布状态" prop="published" min-width="110" align="center" sortable="custom">
          <template slot-scope="scope">
            <span class="common-cell common-cell-right">{{ scope.row.published == true ? '已发布' : '未发布' }}</span>
          </template>
        </el-table-column>
        <el-table-column label="启停用状态" prop="enabled" min-width="130" align="center" sortable="custom">
          <template slot-scope="scope">
            <span class="common-cell common-cell-right">{{ scope.row.enabled == true ? '启用' : '停用' }}</span>
          </template>
        </el-table-column>
        <el-table-column label="公开课" prop="openCourse" min-width="110" align="center" sortable="custom">
          <template slot-scope="scope">
            <span class="common-cell common-cell-right">{{ scope.row.openCourse == 1 ? '是' : '否' }}</span>
          </template>
        </el-table-column>
        <el-table-column label="资源归属" prop="orgName" min-width="220" align="center" sortable="custom" show-overflow-tooltip>
          <template slot-scope="scope">
            <el-tooltip :content="scope.row.orgFullName || scope.row.orgName" placement="top" effect="dark">
              <span class="common-cell common-cell-right">{{ scope.row.orgName }}</span>
            </el-tooltip>
          </template>
        </el-table-column>
        <el-table-column label="创建人" prop="sysCreateBy" min-width="130" align="center" sortable="custom"  show-overflow-tooltip>
          <template slot-scope="scope">
            <span class="common-cell common-cell-right">{{ scope.row.sysCreateBy }}</span>
          </template>
        </el-table-column>
        <el-table-column label="创建来源" min-width="140" align="center">
          <template slot-scope="scope">
            <span class="common-cell" v-if="scope.row.createFrom === 'teacher'">教师端</span>
            <span class="common-cell" v-else-if="scope.row.createFrom === 'admin'">管理端</span>
            <span class="common-cell" v-else>-</span>
          </template>
        </el-table-column>
        <el-table-column label="创建时间" prop="sysCreateTime" min-width="200" show-overflow-tooltip align="center"
          sortable="custom">
          <template slot-scope="scope">
            <span class="common-cell">{{ scope.row.sysCreateTime }}</span>
          </template>
        </el-table-column>
        <el-table-column label="操作" min-width="300px" fixed="right" header-align="center" align="left">
          <template slot-scope="scope" class="btn-gl">
            <template v-if="getInlineActions(scope.row).length">
              <span v-for="(action, index) in getInlineActions(scope.row)" :key="action.key">
                <el-button
                  type="text"
                  size="mini"
                  :class="action.className"
                  @click="handleAction(action.key, scope.row)"
                >
                  {{ action.label }}
                </el-button>
                <el-divider
                  v-if="index < getInlineActions(scope.row).length - 1 || (index === getInlineActions(scope.row).length - 1 && getDropdownActions(scope.row).length)"
                  direction="vertical"
                ></el-divider>
              </span>
            </template>
            <el-dropdown
              v-if="getDropdownActions(scope.row).length"
              type="text"
              size="mini"
              style="margin-left:0px"
              trigger="click"
            >
              <el-button type="text" size="mini" class="action-link--more">
                更多<i class="el-icon-arrow-down el-icon--right"></i>
              </el-button>
              <el-dropdown-menu slot="dropdown">
                <el-dropdown-item
                  v-for="action in getDropdownActions(scope.row)"
                  :key="action.key"
                  :class="action.className"
                  @click.native="handleAction(action.key, scope.row)"
                >
                  {{ action.label }}
                </el-dropdown-item>
              </el-dropdown-menu>
            </el-dropdown>
          </template>
        </el-table-column>
      </el-table>
      <div class="pagination">
        <el-pagination background @size-change="handleSizeChange" @current-change="handleCurrentChange"
          :current-page="page.pageIndex" :page-sizes="[10, 20, 30, 40]" :page-size="page.pageSize"
          layout="total, sizes, prev, pager, next, jumper" :total="page.count"></el-pagination>
      </div>
    </div>

    

    <!-- <div style="height: 100px;"></div> -->
    <!--邀请审核-->
    <el-dialog custom-class="g-dialog" title="邀请教师审核课程" :visible.sync="inviteTeacher.dlgShow">
      <div style="display: flex;justify-content:flex-start;padding-bottom: 10px;">
        <div style="padding: 0px 5px;"><el-input placeholder="姓名" v-model="inviteTeacher.params.name"></el-input></div>
        <div style="padding: 0px 5px;"><el-button @click="findTeachers()" icon="el-icon-search"
            type="primary">搜索</el-button></div>
      </div>
      <div>
        <el-table max-height="500" border :data="inviteTeacher.list" style="width: 100%">
          <el-table-column prop="name" label="姓名" width="180"></el-table-column>
          <el-table-column prop="sex" label="性别"></el-table-column>
          <el-table-column prop="code" label="工号"></el-table-column>
          <el-table-column prop="orgInfo" label="组织"></el-table-column>
          <el-table-column prop="orgInfo" label="选择">
            <template slot-scope="scope">
              <el-radio v-model="scope.row.checked">选择</el-radio>
            </template>
          </el-table-column>
        </el-table>
      </div>
      <template #footer>
        <el-button @click="inviteTeacher.dlgShow = false">取 消</el-button>
        <el-button type="primary" @click="enSure">确认</el-button>
      </template>
    </el-dialog>
    <!--课程管理-->
    <el-dialog custom-class="g-dialog" title="课程学习管理" width="900px" height="900px" :visible.sync="manageStudy.dlgShow"
      :close-on-click-modal="false">
      <manager :manageStudyData="manageStudyData" :isShowDialog="manageStudy.dlgShow"></manager>
      <template #footer>
        <el-button @click="manageStudy.dlgShow = false">关闭</el-button>
      </template>
    </el-dialog>
    <el-dialog title="二维码" :visible.sync="qrCodedialogVisible" width="700px" @close="closeCode" class="common-course-dialog">
      <div>
        <el-form size="medium" label-width="70px">
          <el-form-item label="二维码">
            <div id="qrcode" ref="qrcode" class="qrcode-img" @mouseenter="showDownloadButton = true"
              @mouseleave="showDownloadButton = false">
              <div v-show="showDownloadButton" @click="downloadQrcode" class="downloadn-container">
                <i class="el-icon-download" style="color: #409EFF;font-size:18px;margin-bottom:5px"></i>
                <span>下载</span>
              </div>
            </div>
          </el-form-item>
          <el-form-item label="链接">
            <div style="width:500px">
            <el-input v-model="copyUrl" readonly class="input-with-select" id="text">
              <el-button slot="append" @click="handleCopyUrl">复制</el-button>
            </el-input>
            </div>
          </el-form-item>
          <el-form-item label="">上述内容兼容PC端与移动端，您可按需分享。</el-form-item>
        </el-form>
      </div>
      <span slot="footer" class="dialog-footer"><el-button @click="closeCode">关 闭</el-button></span>
    </el-dialog>
    <!-- 审核 -->
    <el-dialog title="审核" :visible.sync="dialogVisible" width="900px" custom-class="g-dialog">
      <div v-show="expandDetails">
        <div v-if="examin.detailType == 10">
          <auditCourse1 :id="examin.examineId"></auditCourse1>
        </div>
        <div v-if="examin.detailType == 20">
          <auditCourse2 :id="examin.examineId"></auditCourse2>
        </div>
      </div>
      <div style="border-top: 1px solid #eee; background-color: #eee; padding: 5px;">
        <div style="  text-align: center;margin-bottom: 10px;">
          <el-button @click="expandDetails = !expandDetails">{{ expandDetails ? '详情折叠' : '详情展开' }}</el-button>
          <el-button @click="isExamine = 1">直接审核</el-button>
          <el-button @click="isExamine = 2">邀请审核</el-button>
        </div>

        <el-form label-width="80px" v-if="isExamine === 1">
          <el-form-item label="审核">
            <el-radio-group v-model="auditInfo.pass">
              <el-radio :label="true">通过</el-radio>
              <el-radio :label="false">不通过</el-radio>
            </el-radio-group>
          </el-form-item>
          <el-form-item label="审核意见"><el-input v-model="auditInfo.remark" type="textarea"
              rows="3"></el-input></el-form-item>
        </el-form>
        <div v-if="isExamine === 2">
          <div style="display: flex;justify-content:flex-start;padding-bottom: 10px;">
            <div style="padding: 0px 5px;"><el-input placeholder="姓名" v-model="inviteTeacher.params.name"></el-input>
            </div>
            <div style="padding: 0px 5px;"><el-button @click="findTeachers()" icon="el-icon-search"
                type="primary">搜索</el-button></div>
          </div>
          <div>
            <el-table v-if="inviteTeacher.list.length !== 0" max-height="500" border :data="inviteTeacher.list"
              style="width: 100%;margin-bottom: 10px;">
              <el-table-column prop="name" label="姓名" width="180"></el-table-column>
              <el-table-column prop="code" label="工号"></el-table-column>
              <el-table-column prop="orgInfo" label="组织"></el-table-column>
              <el-table-column prop="orgInfo" label="选择">
                <template slot-scope="scope">
                  <el-radio v-model="scope.row.checked">选择</el-radio>
                </template>
              </el-table-column>
            </el-table>
            <div>审核记录：</div>
            <el-table max-height="500" border :data="inviteTeacher.list" style="width: 100%;">
              <el-table-column prop="name" label="姓名" width="180"></el-table-column>
              <el-table-column prop="code" label="工号"></el-table-column>
              <el-table-column prop="orgInfo" label="组织"></el-table-column>
              <el-table-column prop="type" label="审核状态"></el-table-column>
              <el-table-column prop="text" label="备注"></el-table-column>
            </el-table>
          </div>
        </div>
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button @click="dialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="examineData()">提交</el-button>
      </span>
    </el-dialog>
    <el-dialog v-if="showDetails" title="课程详情" :visible.sync="showDetails" @close="examin = {};" width="900px"
      custom-class="g-dialog">
      <div v-show="expandDetails">
        <div v-if="examin.detailType == 10">
          <auditCourse1 :showTest="true" :isDetails="false" :isShow="false" :id="examin.examineId"></auditCourse1>
        </div>
        <div v-if="examin.detailType == 20">
          <auditCourse2 :showTest="true" :isDetails="false" :isShow="false" :id="examin.examineId"></auditCourse2>
        </div>
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button @click="showDetails = false; examin = {};">取 消</el-button>
      </span>
    </el-dialog>
    <div>
      <course-form ref="courseForm" @submitSuccess="searchData" @close="searchData"></course-form>
    </div>
    <top-course-sorter v-if="showSetTopFeature" ref="topSorter" @sorted="onTopSorted"></top-course-sorter>
    <!-- AI 播放器相关：AI翻译 / 开启AI处理 / AI设置 三个弹框 -->
    <!-- 设置语种弹框 -->
    <el-dialog
      title="AI翻译"
      :visible.sync="languageSetting.dlgShow"
      width="500px"
      :close-on-click-modal="false"
    >
      <div style="margin-bottom: 20px;">
        <div style="margin-bottom: 15px;">请选择课程所支持语种</div>
        <el-select
          v-model="languageSetting.languageCode"
          multiple
          placeholder="请选择语种"
          style="width: 100%;"
        >
          <el-option
            v-for="lang in selectAllLang"
            :key="lang.srclang"
            :label="lang.label"
            :value="lang.srclang"
          ></el-option>
        </el-select>
      </div>
      <div style="color: #ff4d4f; font-size: 12px;">
        注：仅支持对已开启AI处理的课程进行批量语种设置；所选的课程中有{{languageSetting.aiSetNoNum}}个未开启AI处理的课程，以上配置仅对{{languageSetting.aiSetNum}}个已开启AI处理的课程生效。
      </div>
      <template #footer>
        <el-button @click="languageSetting.dlgShow = false">取消</el-button>
        <el-button type="primary" @click="confirmLanguageSetting">确认</el-button>
      </template>
    </el-dialog>

    <!-- 开启AI处理弹框 -->
    <el-dialog
      title="开启AI处理"
      :visible.sync="aiProcessSetting.dlgShow"
      width="400px"
    >
      <div class="ai-process-dialog">
        <!-- AI处理状态 -->
        <div class="form-item">
          <span class="form-label">
            <el-tooltip class="item" effect="dark" :content="aiSetTip" placement="top">
              <i class="el-icon-question"></i>
            </el-tooltip>
            AI处理：
          </span>
          <span class="status-text">
            {{ aiProcessSetting.aiSet === 1 ? '开启' : '关闭' }}
          </span>
          <el-switch
            v-model="aiProcessSetting.aiSet"
            :active-value="1"
            :inactive-value="0"
          ></el-switch>
        </div>

        <div v-show="aiProcessSetting.aiSet === 1">
          <!-- 是否生成AI摘要 -->
          <div class="form-item">
            <span class="form-label">
              <el-tooltip class="item" effect="dark" :content="aiAbstractTip" placement="top">
                <i class="el-icon-question"></i>
              </el-tooltip>
              AI摘要：
            </span>
            <span class="status-text">
              {{ aiProcessSetting.aiAbstract === 1 ? '开启' : '关闭' }}
            </span>
            <el-switch
              v-model="aiProcessSetting.aiAbstract"
              :active-value="1"
              :inactive-value="0"
            >
            </el-switch>
          </div>

          <!-- 是否生成AI文稿 -->
          <div class="form-item">
            <span class="form-label">
              <el-tooltip class="item" effect="dark" :content="aiDraftTip" placement="top">
                <i class="el-icon-question"></i>
              </el-tooltip>
              AI文稿：
            </span>
            <span class="status-text">
              {{ aiProcessSetting.aiDraft === 1 ? '开启' : '关闭' }}
            </span>
            <el-switch
              v-model="aiProcessSetting.aiDraft"
              :active-value="1"
              :inactive-value="0"
            >
            </el-switch>
          </div>

          <!-- 课程支持语种选择 -->
          <div class="form-item" style="flex-flow: column;align-items: baseline;">
            <span class="form-label">
              <el-tooltip class="item" effect="dark" :content="aiTranslateTip" placement="top">
                <i class="el-icon-question"></i>
              </el-tooltip>
              AI翻译语种：
            </span>
            <el-select
              v-model="aiProcessSetting.languageCode"
              multiple
              style="width: 100%;"
              placeholder="请选择语种"
            >
              <el-option
                v-for="lang in selectAllLang"
                :key="lang.srclang"
                :label="lang.label"
                :value="lang.srclang"
              ></el-option>
            </el-select>
          </div>
        </div>

        <!-- 提示信息 -->
        <div class="tips">
          <span>注：已跳过{{aiProcessSetting.aiSetNum}}个已开启AI处理的课程，仅更新剩余{{aiProcessSetting.aiSetNoNum}}个</span>
        </div>
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button @click="aiProcessSetting.dlgShow = false">取消</el-button>
        <el-button type="primary" @click="confirmAiProcess">确认</el-button>
      </span>
    </el-dialog>

    <!-- AI设置弹框 -->
    <el-dialog
      title="AI设置"
      :visible.sync="aiSetting.dlgShow"
      width="500px"
    >
      <div class="ai-setting-dialog">
        <!-- AI功能状态 -->
        <div class="form-item">
          <span class="form-label">
            <el-tooltip class="item" effect="dark" content="是否将课程进行AI处理" placement="top">
              <i class="el-icon-question"></i>
            </el-tooltip>
            AI功能状态：
          </span>
          <span class="status-text">
            {{ aiSetting.aiSet === 1 ? '已开放' : '未开放' }}
          </span>
          <el-switch
            v-model="aiSetting.aiSet"
            :active-value="1"
            :inactive-value="0"
          ></el-switch>
        </div>
        <div v-show="aiSetting.aiSet === 1">
          <!-- AI摘要状态 -->
          <div class="form-item">
            <span class="form-label">AI摘要状态：</span>
            <span :class="aiSetting.aiAbstract === 1 ? 'custom-putaway' : 'custom-takeout'">
              {{ aiSetting.aiAbstract === 1 ? '已上架' : '已下架' }}
            </span>
            <div class="action-buttons">
              <el-button type="text" @click="changeAIKey('aiAbstract')">
                {{ aiSetting.aiAbstract === 1 ? '下架' : '上架' }}
              </el-button>
              <el-button v-show="false" type="text">编辑</el-button>
            </div>
          </div>

          <!-- AI文稿状态 -->
          <div class="form-item">
            <span class="form-label">AI文稿状态：</span>
            <span :class="aiSetting.aiDraft === 1 ? 'custom-putaway' : 'custom-takeout'">
              {{ aiSetting.aiDraft === 1 ? '已上架' : '已下架' }}
            </span>
            <div class="action-buttons">
              <el-button type="text" @click="changeAIKey('aiDraft')">
                {{ aiSetting.aiDraft === 1 ? '下架' : '上架' }}
              </el-button>
            </div>
          </div>

          <!-- AI翻译状态 -->
          <div class="form-item">
            <span class="form-label">AI翻译状态：</span>
            <span :class="aiSetting.aiTranslate === 1 ? 'custom-putaway' : 'custom-takeout'">
              {{ aiSetting.aiTranslate === 1 ? '已上架' : '已下架' }}
            </span>
            <div class="action-buttons">
              <el-button type="text" @click="changeAIKey('aiTranslate')">
                {{ aiSetting.aiTranslate === 1 ? '下架' : '上架' }}
              </el-button>
              <el-button v-show="false" type="text">编辑</el-button>
            </div>
          </div>

          <!-- 支持语种 -->
          <div class="form-item" style="align-items: flex-start;">
            <span class="form-label" style="white-space: nowrap;">支持语种：</span>
            <div class="languages-list" v-show="false">
              <div v-for="lang in aiSetting.languageCode" :key="lang" class="language-tag">
                {{ getLanguageName(lang) }}
                <span class="custom-takeout">已下架</span>
              </div>
            </div>
            <el-select
              v-model="aiSetting.languageCode"
              multiple
              style="width: 100%;"
              placeholder="请选择语种"
            >
              <el-option
                v-for="lang in selectAllLang"
                :key="lang.srclang"
                :label="lang.label"
                :value="lang.srclang"
              ></el-option>
            </el-select>
          </div>
        </div>
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button @click="aiSetting.dlgShow = false">取消</el-button>
        <el-button type="primary" @click="confirmAISetting">确认</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
import courseForm from '@/components/Course/courseForm.vue';
import manager from '@/components/Study/manager.vue';
import QRCode from 'qrcodejs2';
import auditCourse1 from '@/components/Course/auditCourse1.vue';
import auditCourse2 from '@/components/Course/auditCourse2.vue';
import adminPage from '@/components/Administration/adminPage.vue';
import TopCourseSorter from '@/components/Course/TopCourseSorter.vue';
import apiResowner from '../../api/modules/resowner.js';
import apiType from '../../api/modules/type.js'
import { courseType, deepCopy } from '../../utils/tools.js';
import apiCourse from '@/api/modules/course.js';
// import {resOwnerIndexName,sysTypeIndexName} from '@/utils/type.js';
import { mapGetters, mapActions } from 'vuex';
import apiUserbasic from "@/api/boe/userbasic.js"
import apiTeacher from '../../api/modules/teacher.js';
export default {
  name: 'manageCourse',
  components: { courseForm, manager, auditCourse1, auditCourse2, adminPage, TopCourseSorter },
  computed: {
    ...mapGetters(['resOwnerMap', 'sysTypeMap', 'userInfo', 'identity', 'selectAllLang']),
    resOwnerCascaderProps() {
      // 搜索模式：关闭懒加载，直接使用全量 options
      if (this.resOwnerSearchMode) {
        return {
          value: 'id',
          label: 'name',
          children: 'children',
          checkStrictly: true, // 允许选择任意一级选项
        };
      }
      // 非搜索模式：开启前端“伪懒加载”，数据从本地缓存树中按需取
      return {
        value: 'id',
        label: 'name',
        children: 'children',
        lazy: true,
        lazyLoad: this.loadResOwnerNodeFromCache,
        checkStrictly: true, // 允许选择任意一级选项
      };
    },
    // 动态计算“授课教师”列的最小宽度，避免固定 260px
    teacherColumnWidth() {
      return this.calcColumnWidth('授课教师', 'teacherName');
    }
  },
  data() {
    return {
      audiences: [],
      forChoose: false,
      pageManage: false,
      showDetails: false,
      examin: {
        detailType: '',
        examineId: '',
        examineName: '',
      },
      paperJson: { items: [] },
      courseType: courseType,
      sysTypeListMap: [],
      sysTypeList: [],
      resOwnerListMap: [],
      resOwnerSelected: [],
      // 资源归属全量树 & 级联选项
      resOwnerTreeAll: [],
      resOwnerOptions: [],
      // 资源归属搜索模式开关（有关键字时为 true）
      resOwnerSearchMode: false,
      showSetTopFeature: false,
      page: {
        pageIndex: 1,//第几页
        pageSize: 10, // 每页多少条
        count: 0
      },
      exportLoading: false,
      resOwner: [],
      resOwnerFilterWarned: false,
      orgId: '',
      orgName: '',
      defaultProps: {
        value: 'code',
        label: 'name',
      },
      defaultTypeProps: {
        value: 'id',
        label: 'name',
      },
      showAdvancedFilter: false,
      learningTimeRange: [],
      pickerOptions: { shortcuts: [] },
      manageStudyData: {},
      expandDetails: true,
      qrCodedialogVisible: false,
      copyUrl: '',
      qrcodeImgUrl: '',
      showDownloadButton: false,
      isExamine: 1,
      auditInfo: {
        pass: true,
        remark: ''
      },
      dialogVisible: false,
      currentPage4: 4,
      inviteTeacher: {
        //邀请
        dlgShow: false,
        params: { name: '' },
        list: []
      },
      manageStudy: {
        dlgShow: false
      },
      params: {
        name: '',
        teacherId: '',
        learningTimeStart: '',
        learningTimeEnd: '',
        status: '',
        publish: '',
        enabled: '',
        openCourse: '',
        createUserId: '',
        createFrom: '',
      },
      orderField: '', // 排序字段
      orderAsc: true, // 排序顺序：true-升序，false-降序
      pageData: [],
      courseChooseShow: false,
      courseChooseId: '',
      teacherFilterList: [],
      teacherSelected: [],
      teacherOptions: [],
      teacherLoading: false,
      creatorSelected: [],
      creatorOptions: [],
      creatorLoading: false,
      courseTypes: [
        { id: '1', img: this.webBaseUrl + '/images/ctype1.png', name: '微课', info: '一种单一课件的课程' },
        { id: '2', img: this.webBaseUrl + '/images/ctype2.png', name: '在线课', info: '有章节多课件的课程' },
        { id: '3', img: this.webBaseUrl + '/images/ctype3.png', name: '课程包', info: '微课和在线课组成' },
        { id: '4', img: this.webBaseUrl + '/images/ctype4.png', name: '线下课', info: 'XXXX' },
        { id: '5', img: this.webBaseUrl + '/images/ctype5.png', name: '直播课', info: 'XXXX' }
      ],
      weike: {
        onlyRequired: false,
        dlgShow: false,
        fileType: '',
        info: {
          shebei: ''
        }
      },
      biaoke: {
        dlgShow: false
      },
      recommend: {
        dlgShow: false,
      },
      catalogs: {
        addNewZhang: false,
        addNewCell: false,
      },
      extendRefId: '',
      extendRefType: '',
      scrollbarStyleApplied: false,
      // AI 播放器相关
      aiPermission: false,
      selectedCourses: [],
      languageSetting: {
        dlgShow: false,
        languageCode: ['zh-CN', 'en-US'],
        aiSetNum: 0,
        aiSetNoNum: 0
      },
      aiProcessSetting: {
        dlgShow: false,
        aiSet: 1,
        aiAbstract: 1,
        aiDraft: 1,
        languageCode: ['zh-CN', 'en-US'],
        aiSetNum: 0,
        aiSetNoNum: 0
      },
      aiSetting: {
        dlgShow: false,
        courseId: '',
        aiSet: 1,
        aiAbstract: 1,
        aiDraft: 1,
        aiTranslate: 1,
        languageCode: ['zh-CN', 'en-US', 'vi-VN']
      },
      aiSetTip: '是否将课程进行AI处理',
      aiAbstractTip: '一键提炼课程视频核心要点，助力学员课前高效掌握重点，快速筛选学习资源',
      aiDraftTip: '分段展示视频内容并精准同步时间轴，实现视频进度与文稿双向定位，学习内容触手可及',
      aiTranslateTip: '智能转换视频字幕与语音为多语种，支持全球学员按需切换语言，打破学习边界',
    };
  },
  created() {
    this.pickerOptions = this.buildPickerOptions();
  },
  mounted() {
    this.getAiPermission();
    this.getAudiences()
    let chooseFlag = this.$route.query.f;
    this.extendRefId = this.$route.query.refId;
    this.extendRefType = this.$route.query.refType;
    if (chooseFlag && chooseFlag == 'choose') {
      this.forChoose = true;
    }

    if (this.$route.query && this.$route.query.page && this.$route.query.page == 'manage') {
      this.pageManage = true;
    }

    if (this.$route.query && this.$route.query.open && this.$route.query.open == 'new') {
      this.addNewCourse();
    }
    this.loadShowSetTopFlag();
    // this.getTree();
    // this.getTypeData();
    // this.searchData();
    this.getResOwnerTree().then(rs => {
      this.resOwnerListMap = rs;
    });
    // 取消全局课程分类
    this.getSysTypeTree().then(rs => {
      this.sysTypeListMap = rs;
    })
    //已经加载tree的情况下，不需要再单独的加载一次
    this.loadResOwners();
    this.loadSysTypes();
    // 加载资源归属全量树，供级联和搜索使用
    this.loadAllResOwnerTree();
    document.querySelector('#app').style.overflowX = 'hidden';
    this.applyAppScrollbarStyle();

  },
  methods: {
    toggleAdvancedFilter() {
      this.showAdvancedFilter = !this.showAdvancedFilter;
    },
    // 计算文本宽度（通过隐藏 span 获取实际宽度）
    getTextWidth(text = '') {
      if (typeof document === 'undefined') return 0;
      const span = document.createElement('span');
      span.innerText = text;
      span.style.cssText = 'position:absolute;visibility:hidden;font-size:14px;font-family:inherit;white-space:nowrap;';
      document.body.appendChild(span);
      const { width } = span.getBoundingClientRect();
      document.body.removeChild(span);
      return Math.ceil(width);
    },
    // 计算列宽（头+内容取最大值，加 padding，并控制最小值）
    calcColumnWidth(label, prop, padding = 24, min = 260, max = Infinity) {
      const contents = (this.pageData || []).map(row => this.getTextWidth((row && row[prop]) || ''));
      const maxContentWidth = contents.length ? Math.max(...contents) : 0;
      const labelWidth = this.getTextWidth(label || '');
      const baseWidth = Math.max(maxContentWidth, labelWidth) + padding;
      const clamped = Math.max(min, Math.min(baseWidth, max));
      return `${clamped}px`;
    },
    applyAppScrollbarStyle() {
      if (this.scrollbarStyleApplied || typeof document === 'undefined') return;
      if (document.getElementById('app-scrollbar-style')) {
        this.scrollbarStyleApplied = true;
        return;
      }
      const style = document.createElement('style');
      style.id = 'app-scrollbar-style';
      style.innerHTML = `
        #app::-webkit-scrollbar {
          width: 6px;
          height: 8px;
        }
        #app::-webkit-scrollbar-thumb {
          border-radius: 4px;
          background-color: #4284F7;
        }
        #app::-webkit-scrollbar { 
          width: 6px;
          height: 6px;
          background-color:rgba(0, 0, 0, .1);
          border-radius: 4px;
        }
      `;
      document.head.appendChild(style);
      this.scrollbarStyleApplied = true;
    },
    async loadShowSetTopFlag() {
      try {
        const res = await apiCourse.showSetTop();
        this.showSetTopFeature = res && res.status === 200 && res.result === true;
      } catch (error) {
        this.showSetTopFeature = false;
      }
    },
    async remoteSearchTeacher(keyword) {
      const limited = (keyword || '').slice(0, 50);
      if (this.$refs.teacherSelect && this.$refs.teacherSelect.query !== limited) {
        this.$refs.teacherSelect.query = limited;
        this.$nextTick(() => {
          if (this.$refs.teacherSelect && this.$refs.teacherSelect.$refs && this.$refs.teacherSelect.$refs.input) {
            this.$refs.teacherSelect.$refs.input.value = limited;
          }
        });
      }
      const query = limited.trim();
      if (!query || query.length <= 1) {
        this.teacherOptions = [];
        return;
      }
      this.teacherLoading = true;
      try {
        const res = await apiTeacher.findByNameNew(query);
        if (res && res.code === 200) {
          const teacherList = res.data || [];
          this.teacherOptions = teacherList
            .map(item => this.formatTeacherItem(item))
            .filter(item => item.teacherId);
        } else {
          this.teacherOptions = [];
        }
      } catch (error) {
        this.teacherOptions = [];
      } finally {
        this.teacherLoading = false;
      }
    },
    formatTeacherItem(item = {}) {
      return {
        teacherId: item.id,
        teacherName: item.name,
        teacherCode: item.mobile || '',
      };
    },
    formatTeacherLabel(item = {}) {
      if (!item.teacherName) {
        return '';
      }
      return item.teacherCode ? `${item.teacherName}(${item.teacherCode})` : item.teacherName;
    },
    handleTeacherChange(value = []) {
      this.params.teacherId = (value || []).join(',');
      this.adjustTeacherWidth();
    },
    handleTeacherClear() {
      this.teacherSelected = [];
      this.teacherOptions = [];
      this.params.teacherId = '';
    },
    // 授课教师下拉展开时，如果当前没有关键字，则清空上一次的查询结果
    handleTeacherVisibleChange(visible) {
      if (!visible) return;
      // 打开时才处理
      const select = this.$refs.teacherSelect;
      const query = (select && select.query) || '';
      if (!query) {
        this.teacherOptions = [];
      }
    },
    async remoteSearchCreator(keyword) {
      const limited = (keyword || '').slice(0, 50);
      if (this.$refs.creatorSelect && this.$refs.creatorSelect.query !== limited) {
        this.$refs.creatorSelect.query = limited;
        this.$nextTick(() => {
          if (this.$refs.creatorSelect && this.$refs.creatorSelect.$refs && this.$refs.creatorSelect.$refs.input) {
            this.$refs.creatorSelect.$refs.input.value = limited;
          }
        });
      }
      const query = limited.trim();
      if (!query || query.length <= 1) {
        this.creatorOptions = [];
        return;
      }
      this.creatorLoading = true;
      try {
        const res = await apiUserbasic.selectUser(query);
        if (res && res.status === 200) {
          const resultList = res.result || [];
          this.creatorOptions = resultList
            .map(item => this.formatCreatorItem(item))
            .filter(item => item.userId);
        } else {
          this.creatorOptions = [];
        }
      } catch (error) {
        this.creatorOptions = [];
      } finally {
        this.creatorLoading = false;
      }
    },
    formatCreatorItem(item = {}) {
      return {
        userId: item.id,
        name: item.realName,
        code: item.userNo,
      };
    },
    formatCreatorLabel(item = {}) {
      if (!item.name) {
        return '';
      }
      return item.code ? `${item.name}(${item.code})` : item.name;
    },
    handleCreatorChange(value = []) {
      this.params.createUserId = (value || []).slice(0, 5).join(',');
      this.adjustCreatorWidth();
    },
    handleCreatorClear() {
      this.creatorSelected = [];
      this.params.createUserId = '';
      this.adjustCreatorWidth();
    },
    // 创建人下拉展开时，如果当前没有关键字，则清空上一次的查询结果
    handleCreatorVisibleChange(visible) {
      if (!visible) return;
      const select = this.$refs.creatorSelect;
      const query = (select && select.query) || '';
      if (!query) {
        this.creatorOptions = [];
      }
    },
    limitTeacherInput(event) {
      const limited = (event && event.target && event.target.value ? event.target.value : '').slice(0, 50);
      if (event && event.target && event.target.value !== limited) {
        event.target.value = limited;
      }
      if (this.$refs.teacherSelect) {
        this.$refs.teacherSelect.query = limited;
      }
      this.adjustTeacherWidth();
    },
    limitCreatorInput(event) {
      const limited = (event && event.target && event.target.value ? event.target.value : '').slice(0, 50);
      if (event && event.target && event.target.value !== limited) {
        event.target.value = limited;
      }
      if (this.$refs.creatorSelect) {
        this.$refs.creatorSelect.query = limited;
      }
      this.adjustCreatorWidth();
    },
    limitResOwnerInput(event) {
      const limited = (event && event.target && event.target.value ? event.target.value : '').slice(0, 200);
      if (event && event.target && event.target.value !== limited) {
        event.target.value = limited;
      }
      const keyword = (limited || '').trim();
      // 根据是否有关键字切换搜索模式
      this.resOwnerSearchMode = !!keyword;
      if (this.resOwnerSearchMode) {
        // 搜索模式：使用全量树作为 options，交给 filter-method 过滤
        this.resOwnerOptions = this.resOwnerTreeAll;
      } else {
        // 非搜索模式：清空 options，交给 lazyLoad 从缓存树按需“懒加载”
        this.resOwnerOptions = [];
      }
    },
    // 清空选择时，恢复到懒加载模式
    handleResOwnerClear() {
      this.resOwnerSearchMode = false;
      this.resOwnerOptions = [];
      // 清空输入框的文字，避免残留关键字
      this.$nextTick(() => {
        if (this.$refs.resOwnerCascader && this.$refs.resOwnerCascader.inputValue !== undefined) {
          this.$refs.resOwnerCascader.inputValue = '';
        }
      });
    },
    // 下拉面板打开时，如果当前没有关键字，也确保是懒加载模式
    handleResOwnerVisibleChange(visible) {
      if (!visible) return;
      // 如果没有关键字，就强制回到懒加载模式
      const keyword = (this.$refs.resOwnerCascader && this.$refs.resOwnerCascader.inputValue) || '';
      if (!keyword) {
        this.resOwnerSearchMode = false;
        this.resOwnerOptions = [];
      }
    },
    resOwnerFilterMethod(node, keyword) {
      if (!keyword) return true;
      // 只对叶子节点做匹配，避免同一个名称在父/子层级出现时，看起来像“重复数据”
      const isLeaf = node.isLeaf || (node.data && node.data.leaf);
      if (!isLeaf) return false;
      const text = (node.label || (node.data && node.data.name) || '').toString().toLowerCase();
      const kw = keyword.toString().toLowerCase();
      return text.includes(kw);
    },
    handleTopSort() {
      if (this.$refs.topSorter) {
        this.$refs.topSorter.open();
      }
    },
    onTopSorted() {
      this.searchData(true);
    },
    handleLearningTimeRangeChange(val) {
      if (val && val.length === 2) {
        this.params.learningTimeStart = val[0];
        this.params.learningTimeEnd = val[1];
      } else {
        this.params.learningTimeStart = '';
        this.params.learningTimeEnd = '';
      }
    },
    buildPickerOptions() {
      const shortcutConfigs = [
        {
          text: '今年以来',
          range: () => {
            const end = new Date();
            const start = new Date(end.getFullYear(), 0, 1);
            return [start, end];
          }
        },
        {
          text: '最近一年',
          range: () => {
            const end = new Date();
            const start = new Date();
            start.setTime(end.getTime() - 3600 * 1000 * 24 * 365);
            return [start, end];
          }
        },
        {
          text: '最近三个月',
          range: () => {
            const end = new Date();
            const start = new Date();
            start.setTime(end.getTime() - 3600 * 1000 * 24 * 90);
            return [start, end];
          }
        },
        {
          text: '最近一个月',
          range: () => {
            const end = new Date();
            const start = new Date();
            start.setTime(end.getTime() - 3600 * 1000 * 24 * 30);
            return [start, end];
          }
        },
        {
          text: '最近一周',
          range: () => {
            const end = new Date();
            const start = new Date();
            start.setTime(end.getTime() - 3600 * 1000 * 24 * 7);
            return [start, end];
          }
        }
      ];
      return {
        shortcuts: shortcutConfigs.map(item => ({
          text: item.text,
          onClick: picker => {
            picker.$emit('pick', item.range());
          }
        }))
      };
    },
    validateLearningTimeRange() {
      const hasStart = !!this.params.learningTimeStart;
      const hasEnd = !!this.params.learningTimeEnd;
      if ((hasStart && !hasEnd) || (!hasStart && hasEnd)) {
        this.$showManageMessage('请选择完整的培训时间范围', 'warning');
        return false;
      }
      return true;
    },
    formatCourseDuration(row) {
      // if (row.durationDesc) {
      //   return row.durationDesc;
      // }
      const duration = row.courseDuration
      if (duration === undefined || duration === null || duration === 0) {
        return '0';
      }
      const minutes = Math.round(duration / 60);
      //if (minutes >= 60) {
        //const hours = (minutes / 60).toFixed(1);
        //return `${hours}小时`;
      //}
      return `${minutes || 0}`;
    },
    formatStudyCount(row) {
      const count = row.studyCount !== undefined
        ? row.studyCount
        : (row.studyNum !== undefined ? row.studyNum : (row.learners !== undefined ? row.learners : row.studyUsers));
      if (count === undefined || count === null) {
        return '-';
      }
      return count;
    },
    formatScore(row) {
      let score;
      // 优先取score，其次取avgScore
      if (row.score !== undefined && (row.score || row.score === 0)) {
        score = row.score;
      } else if (row.avgScore !== undefined && (row.avgScore || row.avgScore === 0)) {
        score = row.avgScore;
      } else {
        return '-';
      }

      // 处理数值，四舍五入保留1位小数
      // 先转换为数字类型，避免字符串格式的数值问题
      const numScore = Number(score);
      // 检查是否为有效数字
      if (isNaN(numScore)) {
        return '-';
      }

      // 四舍五入保留1位小数
      return numScore.toFixed(1);
    },
    getDurationNumber(row) {
      const duration = row.duration !== undefined
        ? row.duration
        : (row.studyDuration !== undefined ? row.studyDuration : row.totalDuration);
      if (duration === undefined || duration === null) {
        return 0;
      }
      return Number(duration) || 0;
    },
    sortByDuration(a, b) {
      return this.getDurationNumber(a) - this.getDurationNumber(b);
    },
    formatSysTypeChain(row = {}) {
      const codes = [row.sysType1, row.sysType2, row.sysType3];
      const names = codes
        .filter(code => code !== undefined && code !== null && code !== '')
        .map(code => this.sysTypeName(code))
        .filter(name => name && name !== '');
      return names.length ? names.join('/') : '';
    },
    sysTypeName(code) {
      // console.log('code', code);
      // console.log('this.sysTypeMap', this.sysTypeMap);
      if (code == '') { return ''; }
      return this.sysTypeMap.get(code);
    },
    getStudyCountNumber(row) {
      const count = row.studyCount !== undefined
        ? row.studyCount
        : (row.studyNum !== undefined ? row.studyNum : (row.learners !== undefined ? row.learners : row.studyUsers));
      if (count === undefined || count === null) {
        return 0;
      }
      return Number(count) || 0;
    },
    sortByStudyCount(a, b) {
      return this.getStudyCountNumber(a) - this.getStudyCountNumber(b);
    },
    getScoreNumber(row) {
      if (row.score || row.score === 0) {
        return Number(row.score) || 0;
      }
      if (row.avgScore || row.avgScore === 0) {
        return Number(row.avgScore) || 0;
      }
      return 0;
    },
    sortByScore(a, b) {
      return this.getScoreNumber(a) - this.getScoreNumber(b);
    },
    getOrderNumber(row) {
      if (row.orderIndex || row.orderIndex === 0) {
        return Number(row.orderIndex) || 0;
      }
      if (row.orderValue || row.orderValue === 0) {
        return Number(row.orderValue) || 0;
      }
      if (row.sortIndex || row.sortIndex === 0) {
        return Number(row.sortIndex) || 0;
      }
      return 0;
    },
    sortByOrderValue(a, b) {
      return this.getOrderNumber(a) - this.getOrderNumber(b);
    },
    formatOrderValue(row) {
      if (row.orderIndex || row.orderIndex === 0) {
        return row.orderIndex;
      }
      if (row.orderValue || row.orderValue === 0) {
        return row.orderValue;
      }
      if (row.sortIndex || row.sortIndex === 0) {
        return row.sortIndex;
      }
      return '-';
    },
    buildQueryParams() {
      const query = {
        ...this.params,
        pageIndex: this.page.pageIndex,
        pageSize: this.page.pageSize,
      };
      Object.keys(query).forEach(key => {
        if (query[key] === '' || query[key] === null) {
          delete query[key];
        }
      });
      const [sysOne = '', sysTwo = '', sysThree = ''] = this.sysTypeList || [];
      query.sysType1 = sysOne;
      query.sysType2 = sysTwo;
      query.sysType3 = sysThree;
      if (this.orgId) {
        query.orgId = this.orgId;
      }
      if (this.params.name) {
        query.keyword = this.params.name;
      }
      if (this.$route.query.courseIds) query.courseIds = this.$route.query.courseIds.split(',');
      if (this.$route.query.projectId) query.projectId = this.$route.query.projectId;
      if (this.audiences && this.audiences.length > 0) {
        query.audiences = this.audiences.join(',');
      }
      query.isCreateCourse = !this.pageManage;
      
      // 添加排序参数
      if (this.orderField) {
        query.orderField = this.orderField;
        query.orderAsc = this.orderAsc;
      }
      
      return query;
    },
    async handleExport() {
      if (!this.validateLearningTimeRange()) {
        return;
      }
      const query = this.buildQueryParams();
      delete query.pageIndex;
      delete query.pageSize;
      this.exportLoading = true;
      try {
        const blob = await apiCourse.exportCourse(query);
        if (!(blob instanceof Blob)) {
          throw new Error('导出失败');
        }
        const link = document.createElement('a');
        const url = window.URL.createObjectURL(blob);
        const timestamp = new Date().toISOString().replace(/[-:T]/g, '').split('.')[0];
        link.href = url;
        link.download = `在线课列表.xlsx`;
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
        window.URL.revokeObjectURL(url);
      } catch (error) {
        this.$showManageMessage(error.message || '导出失败', 'error');
      } finally {
        this.exportLoading = false;
      }
    },
    getAudiences() {
      apiUserbasic.getInAudienceIds().then(res => {
        if (res.status == 200) {
          this.audiences = res.result;
        }
        this.searchData();
      })
    },
    handleChoose(row) { //选择课程
      window.parent.selectCourse(row);
    },
    // 置顶
    setTop(row) {
      let params = {
        ids: row.id,//课程id,多个使用逗号分隔,
        title: row.name,//课程的名称,
        top: !row.isTop,// top 是否置顶}
      }
      console.log(row.isTop);
      if (row.isTop == false) {
        //  console.log('fa')
        apiCourse.setTop(params).then(res => {
          if (res.status === 200 && res.result === true) {
            this.$showManageMessage('置顶成功！', 'success')
            this.searchData();
          } else if (res.status === 500) {
            const confirmText = `<i class="el-icon-warning-outline"></i>已置顶10条课程，若需继续置顶，请对部分课程执行取消置顶操作`;
            this.$confirm(confirmText, '置顶确认', {
              confirmButtonText: '确定',
              cancelButtonText: '取消',
              dangerouslyUseHTMLString: true,
              type: 'warning',
              customClass: 'custom-confirm-dialog'
            }).then(() => {}).catch(() => { });
          } else {
            this.$showManageMessage(res.message, 'error');
          }
        })
      } else if (row.isTop == true) {
        apiCourse.setTop(params).then(res => {
          if (res.status === 200 && res.result === true) {
            this.$showManageMessage('取消成功！', 'success')
            this.searchData();
          } else {
            this.$showManageMessage(res.message, 'error');
          }
        })
      }
    },
    // 复制
    copyCourse(item) {
      const confirmText = `<i class="el-icon-warning-outline"></i>确认复制${item.name}吗？`;
      this.$confirm(confirmText, '复制确认', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        dangerouslyUseHTMLString: true,
        type: 'warning',
        customClass: 'custom-confirm-dialog'
      }).then(() => {
        const reqdata = {
          id: item.id,
          refId: this.extendRefId,
          refType: this.extendRefType,
        };
        apiCourse.copyCourse(reqdata).then(rs => {
          if (rs.status === 200) {
            this.$showManageMessage('复制成功', 'success');
            this.searchData();
          } else {
            this.$showManageMessage(rs.message || '复制失败', 'error');
          }
        }).catch(() => {
          this.$showManageMessage('复制失败', 'error');
        });
      }).catch(() => { });
    },
    // 撤回接口
    withdraw(row) {
      this.$confirm(`确定撤回${row.name}的审核申请吗？`, '撤回确认', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
        customClass: 'custom-confirm-dialog'
      }).then(() => {
        apiCourse.revokeSubmit(row.id).then((res) => {
          if (res.status === 200 && res.result) {
            this.$showManageMessage('撤回成功', 'success');
            this.searchData();
          } else {
            this.$showManageMessage(res.message || '撤回失败', 'error');
          }
        }).catch(() => {
          this.$showManageMessage('撤回失败', 'error');
        });
      }).catch(() => { });
    },
    reset() {
      this.resOwner = [];
      this.sysTypeList = [];
      this.learningTimeRange = [];
      this.orgId = '';
      this.orgName = '';
      this.resOwnerSelected = [];
      this.teacherFilterList = [];
      this.teacherSelected = [];
      this.teacherOptions = [];
      this.teacherLoading = false;
      this.creatorSelected = [];
      this.creatorOptions = [];
      Object.assign(this.params, {
        name: '',
        teacherId: '',
        learningTimeStart: '',
        learningTimeEnd: '',
        status: '',
        publish: '',
        enabled: '',
        openCourse: '',
        createUserId: '',
        createFrom: '',
      });
      // 重置排序
      this.orderField = '';
      this.orderAsc = true;
      this.searchData(true);
    },
    ...mapActions({
      getResOwnerTree: 'resOwner/getResOwnerTree',
      loadResOwners: 'resOwner/loadResOwners',
      getSysTypeTree: 'sysType/getSysTypeTree',
      loadSysTypes: 'sysType/loadSysTypes'
    }),
    resOwnerName(code) {
      if (code == '') { return ''; }
      return this.resOwnerMap.get(code);
    },
    // 直接审核
    examineData() {
      if (this.isExamine == 1) {
        let params = {
          id: this.examin.examineId,//课程id,
          title: this.examin.examineName,//课程的名称,
          pass: this.auditInfo.pass,//Boolean 是否通过,
          remark: this.auditInfo.remark,// 备注
        }
        apiCourse.audit(params).then(res => {
          if (res.status === 200) {
            this.$showManageMessage('操作成功！', 'success');
            this.dialogVisible = false;
            this.searchData();
          } else {
            this.$showManageMessage(res.message, 'error');
          }
        })
      } else {
        this.$showManageMessage('暂未开放！', 'warning');
      }

    },
    addNewCourse() {
      this.$refs.courseForm.initShow();
    },
    editCurriculum(row) {
      this.$refs.courseForm.initShow(row);
    },
    // 课程启停
    async isDisable(row) {
      const nextEnabled = !row.enabled;
      const actionText = nextEnabled ? '启用' : '停用';
      try {
        await this.$confirm(`<i class="el-icon-warning-outline"></i>确定${actionText}${row.name}吗？`, `${actionText}确认`, {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning',
          dangerouslyUseHTMLString: true,
          customClass: 'custom-confirm-dialog'
        });
      } catch (error) {
        return;
      }
      const params = {
        ids: row.id,
        title: row.name,
        enabled: nextEnabled,
      };
      try {
        const { status } = await apiCourse.setEnabled(params);
        if (status === 200) {
          this.$showManageMessage(`${actionText}成功`, 'success');
          row.enabled = nextEnabled;
        } else {
          this.$showManageMessage(`${actionText}失败`, 'error');
        }
      } catch (error) {
        this.$showManageMessage(`${actionText}失败`, 'error');
      }
    },
    // 课程查询
    searchData(pageReset) {
      if (pageReset) {
        this.page.pageIndex = 1;
      }
      if (!this.validateLearningTimeRange()) {
        return;
      }
      console.log('apiCourse', apiCourse);
      console.log('buildQueryParams', this.buildQueryParams());
      const query = this.buildQueryParams();
      apiCourse.managePage(query).then(rs => {
        if (rs.status == 200) {
          this.pageData = rs.result.list ? rs.result.list : [];
          this.page.count = rs.result.count;
          this.page.pageSize = rs.result.pageSize;
        } else {
          return this.$showManageMessage(rs.message, 'error');
        }
      }).catch(err => {
        console.error('查询课程列表失败:', err);
        this.$showManageMessage('查询失败，请稍后重试', 'error');
      });

    },
    // 表格排序变化事件
    handleSortChange({ column, prop, order }) {
      // order: ascending(升序) | descending(降序) | null(取消排序)
      console.log('排序变化:', { column, prop, order });
      
      if (order) {
        // 有排序：保存排序字段和顺序
        this.orderField = prop;
        this.orderAsc = order === 'ascending';
      } else {
        // 取消排序：清空排序字段
        this.orderField = '';
        this.orderAsc = true;
      }
      
      // 重新查询数据
      this.searchData(true);
    },
    viewTopic(row) {
      if (row.status == 1) {
        return this.$showManageMessage('请提交课程再预览！', 'warning')
      }
      this.examin = {};
      this.examin.detailType = row.type;
      this.examin.examineId = row.id;
      this.examin.examineName = row.name;
      this.showDetails = true;
    },
    jumpDetails() {
      // this.$router.push('/course/micro');
      // 跳转打开新页面
      let routeData = this.$router.resolve({ path: '/course/detail' }); // , query: {  id: 1 }
      window.open(this.webBaseUrl + routeData.href, '_blank');
    },
    toExamine(row) {
      this.auditInfo = { pass: true };
      this.examin.detailType = row.type;
      this.examin.examineId = row.id;
      this.examin.examineName = row.name;
      this.dialogVisible = true;
    },
    enSure() {
      // 确认事件
    },
    handleSizeChange(val) {
      this.page.pageSize = val;
      this.page.pageIndex = 1;
      this.searchData();
    },
    handleCurrentChange(val) {
      this.page.pageIndex = val;
      this.searchData();
    },
    chooseInvite(row) {
      //邀请老师审核
      this.inviteTeacher.dlgShow = true;
    },
    findTeachers() {
      this.inviteTeacher.list = [
        { id: '1', name: '李玉冰', type: '通过', text: '实用', sex: '男', code: '1023123', orgInfo: '教育技术中心', checked: false },
        { id: '2', name: '李玉冰', type: '未通过', text: '内容在调整', sex: '男', code: '1023123', orgInfo: '教育技术中心', checked: false },
        { id: '3', name: '李玉冰', type: '驳回', text: '内容重复', sex: '男', code: '1023123', orgInfo: '教育技术中心', checked: false }
      ];
    },
    showQrimage(row) {
      // 使用本页二维码弹窗逻辑
      this.qrCodedialogVisible = true;
      // 与 TeacherList 保持一致的二维码生成逻辑
      this.copyUrl = this.qrcodeImgUrl = `${process.env.VUE_APP_BOE_WEB_URL}/systemapi/xboe/m/course/manage/redirectDetail?courseId=${row.id}`;
      this.$nextTick(() => {
        this.crateQrcode();
      });
    },
    handleCopyUrl() {
      const ele = document.getElementById('text');
      if (!ele) return;
      ele.select();
      document.execCommand('Copy');
      this.$showManageMessage('复制成功', 'success');
    },
    downloadQrcode() {
      const container = document.getElementById('qrcode');
      if (!container) return;
      const img = container.getElementsByTagName('img')[0];
      if (!img) return;
      const canvas = document.createElement('canvas');
      canvas.width = img.width;
      canvas.height = img.height;
      const ctx = canvas.getContext('2d');
      ctx.drawImage(img, 0, 0);
      const tempUrl = canvas.toDataURL('image/png');
      const link = document.createElement('a');
      link.style.display = 'none';
      link.href = tempUrl;
      link.setAttribute('download', '二维码.jpg');
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
    },
    crateQrcode() {
      // eslint-disable-next-line no-new
      new QRCode('qrcode', {
        width: 150,
        height: 150,
        text: this.qrcodeImgUrl
      });
    },
    // 关闭弹框,清除已经生成的二维码
    closeCode() {
      this.qrCodedialogVisible = false;
      // 逐个节点移除，避免事件丢失
      const images = document.querySelectorAll('.qrcode-img img');
      images.forEach(img => img.remove());
      const canvas = document.querySelectorAll('.qrcode-img canvas');
      canvas.forEach(c => c.remove());
    },
    showManageStudy(row) {
      // 带课程详情跳转到课程管理页
      sessionStorage.setItem('courseDetail', JSON.stringify(row));
      this.$router.push({ path: '/iframe/course/coursemanage-remote' });
    },
    // 克隆一个用于懒加载的节点：只保留当前层必要字段，不预置 children，避免 Element Cascader 出现重复节点
    cloneOrgNodeForLazy(node = {}) {
      return {
        id: node.id,
        name: node.name,
        leaf: node.leaf,
      };
    },
    // 前端“伪懒加载”：根据本地全量机构树按需返回子节点
    // 为了让 el-cascader 的 loading 动画有可见效果，这里故意加入一个很小的延时再 resolve
    async loadResOwnerNodeFromCache(node, resolve) {
      try {
        const delayResolve = (nodes) => {
          // 适当延时 150ms，让 loading 动画可见，但又不会让用户感觉明显卡顿
          setTimeout(() => resolve(nodes), 150);
        };

        // 如果当前节点在数据上被标记为叶子节点，直接返回空数组，不再触发“懒加载”
        if (node && node.data && node.data.leaf) {
          return resolve([]);
        }

        // 根节点（level === 0）：返回所有一级机构（只返回当前层的浅拷贝，不带 children，避免重复）
        if (node.level === 0) {
          const roots = (this.resOwnerTreeAll || []).map(item => this.cloneOrgNodeForLazy(item));
          return delayResolve(roots);
        }

        // 其他层级：根据当前节点 id 在树中查找对应节点，再返回其 children
        const currentId = node.value || (node.data && node.data.id);
        if (!currentId) {
          return delayResolve([]);
        }

        const findNodeById = (list = [], id) => {
          for (let i = 0; i < list.length; i++) {
            const item = list[i];
            if (item.id === id) {
              return item;
            }
            if (Array.isArray(item.children) && item.children.length > 0) {
              const found = findNodeById(item.children, id);
              if (found) return found;
            }
          }
          return null;
        };

        const target = findNodeById(this.resOwnerTreeAll || [], currentId);
        if (!target) {
          // 未找到对应节点，直接返回空
          return resolve([]);
        }

        // 如果在树里这个节点本身就是叶子节点，同样直接返回空，不展示 loading
        if (target.leaf) {
          return resolve([]);
        }

        if (Array.isArray(target.children) && target.children.length > 0) {
          // 有子节点时，只返回当前层的浅拷贝，不预置更深 children，避免重复
          const children = target.children.map(child => this.cloneOrgNodeForLazy(child));
          // 做一个轻微延迟，让 loading 有一点点反馈
          return delayResolve(children);
        }

        // 没有子节点，直接返回空
        return resolve([]);
      } catch (e) {
        console.error('本地懒加载资源归属节点失败:', e);
        resolve([]);
      }
    },
    handleResOwnerChange(value) {
      if (!value || value.length === 0) {
        this.orgId = '';
        this.orgName = '';
        // 清空选择时，直接收起下拉
        if (this.$refs.resOwnerCascader) {
          this.$refs.resOwnerCascader.dropDownVisible = false;
        }
        return;
      }
      // value 是选中的路径数组，最后一个元素是选中的节点ID
      const selectedId = value[value.length - 1];
      this.orgId = selectedId;
      
      // 通过级联选择器的 getCheckedNodes 方法获取选中的节点信息
      this.$nextTick(() => {
        if (this.$refs.resOwnerCascader) {
          const checkedNodes = this.$refs.resOwnerCascader.getCheckedNodes();
          if (checkedNodes && checkedNodes.length > 0) {
            const lastNode = checkedNodes[checkedNodes.length - 1];
            this.orgName = lastNode.label || lastNode.name || '';
          }
          // 选中后自动收起下拉
          this.$refs.resOwnerCascader.dropDownVisible = false;
        }
      });
    },
    // 将后端机构节点转换为级联组件所需结构
    mapOrgToCascaderNode(node = {}) {
      const hasChildren = Array.isArray(node.childList) && node.childList.length > 0;
      const children = hasChildren
        ? node.childList.map(child => this.mapOrgToCascaderNode(child))
        : [];
      return {
        id: node.organizationId,
        name: node.orgName,
        children,
        // childList 为空就标记为叶子节点，去掉右侧箭头，且不再触发懒加载
        leaf: !hasChildren,
      };
    },
    // 加载资源归属全量机构树
    async loadAllResOwnerTree() {
      try {
        const res = await apiUserbasic.getAllOrgTree();
        // 调试日志：打印原始机构树与映射后的树结构，用于排查“重复节点”问题
        try {
          const raw = res && res.result && res.result.orgTreeList
            ? JSON.parse(JSON.stringify(res.result.orgTreeList))
            : [];
          // 注意：这里日志仅用于前端调试，确认后可删除
          console.log('[资源归属] getAllOrgTree 原始 orgTreeList =>', raw);
        } catch (e) {
          console.warn('[资源归属] 打印 orgTreeList 日志失败:', e);
        }

        if (res && res.status === 200 && res.result && Array.isArray(res.result.orgTreeList)) {
          this.resOwnerTreeAll = res.result.orgTreeList.map(item => this.mapOrgToCascaderNode(item));
          console.log('[资源归属] 映射后的 resOwnerTreeAll =>', this.resOwnerTreeAll);
          // 默认进入非搜索模式，由懒加载从本地树按需返回节点
          this.resOwnerOptions = [];
        } else if (res && res.result && Array.isArray(res.result.orgTreeList)) {
          // 兼容没有 status 字段但有 result 的情况
          this.resOwnerTreeAll = res.result.orgTreeList.map(item => this.mapOrgToCascaderNode(item));
          console.log('[资源归属] 映射后的 resOwnerTreeAll(无status) =>', this.resOwnerTreeAll);
          this.resOwnerOptions = [];
        } else {
          this.resOwnerTreeAll = [];
          this.resOwnerOptions = [];
        }
      } catch (error) {
        console.error('加载资源归属全量树失败:', error);
        this.resOwnerTreeAll = [];
        this.resOwnerOptions = [];
      }
    },
    showChooseCourse() {
      this.courseChooseShow = true;
    },
    chooseCourseType(item, idx) {
      this.courseChooseId = item.id;
    },
    toInputCourse() {
      if (this.courseChooseId == '1') {
        this.showWeike();
      } else if (this.courseChooseId == '2') {
        this.showBiaoke();
      }
      this.courseChooseShow = false;
    },
    newHandleClick() { },
    showRecords(item) {
      this.recommend.dlgShow = true;
    },
    showWeike() {
      this.weike.dlgShow = true;
    },
    showBiaoke() {
      this.biaoke.dlgShow = true;
    },
    // setTop(item, idx) {
    //   let msg = '已设置置顶';
    //   if (item.isTop) {
    //     item.isTop = false;
    //     msg = '已取消置顶';
    //   } else {
    //     item.isTop = true;
    //   }
//   this.$showManageMessage('xxx', 'success');
    // },
    delItem(row) {
      // this.$showManageMessage('删除成功', 'success');
      // return false
      this.$confirm(`<i class="el-icon-warning-outline"></i>确认删除${row.name}吗？`, '删除确认', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        dangerouslyUseHTMLString: true,
        type: 'warning',
        customClass: 'custom-confirm-dialog'
      }).then(async () => {
        let params = {
          id: row.id,
          title: row.name,

        };
        try {
          //  {id:课程id,多个使用逗号分隔,Boolean erasable 是否物理删除,title:课程的名称, remark 备注}
          const { status } = await apiCourse.del(params);
          if (status === 200) {
            this.$showManageMessage('删除成功', 'success'); //只是之前发布过的课程删除才可
            // if(!row.erasable){
            //   let event = {
            //     key: "CourseDelete",//被管理员删除
            //     title: '被管理员删除课程',//事件的标题
            //     parameters:"author:"+row.sysCreateAid,//作者，一般这种情况不是管理员自己添加的
            //     content: '被管理员删除课程',//事件的内容
            //     objId: row.id,//关联的id
            //     objType: "1",//关联的类型
            //     objInfo:row.name,
            //     aid: this.userInfo.aid, //当前登录人的id
            //     aname: this.userInfo.name,//当前人的姓名
            //     status: 1 //状态，直接写1
            //   }
            //   this.$store.dispatch("userTrigger", event);
            // }

            this.searchData();
          }
        } catch (error) {
          this.$showManageMessage('删除失败', 'error');
        }
      })
        .catch((err) => {
          // this.$showManageMessage('已取消删除', 'info');
        });
    },
    showAddCatalogZhang(bal) {
      this.catalogs.addNewZhang = bal;
    },
    saveNewCatalogZhang() {
      this.catalogs.addNewZhang = false;
    },
    handleAction(key, row) {
      switch (key) {
        case 'edit':
          return this.editCurriculum(row);
        case 'qrcode':
          return this.showQrimage(row);
        case 'manage':
          return this.showManageStudy(row);
        case 'withdraw':
          return this.withdraw(row);
        case 'delete':
          return this.delItem(row);
        case 'copy':
          return this.copyCourse(row);
        case 'toggleEnable':
          return this.isDisable(row);
        case 'toggleTop':
          return this.setTop(row);
        case 'aiSetting':
          return this.setAI(row);
        default:
          return;
      }
    },
    buildActions(row) {
      const actions = [];
      // 优先级按原有展示顺序
      if (this.aiPermission) {
        actions.push({ key: 'aiSetting', label: 'AI设置', className: 'action-link--primary' });
      }
      if (row.isPermission && !this.forChoose && row.status == 2) {
        actions.push({ key: 'withdraw', label: '撤回', className: 'action-link--primary' });
      }
      if (row.isPermission && row.status != 2) {
        actions.push({ key: 'edit', label: '编辑', className: 'action-link--primary' });
      }
      if (row.published) {
        actions.push({ key: 'qrcode', label: '二维码', className: 'action-link--primary' });
      }
      if (row.isPermission && !this.forChoose && row.published) {
        actions.push({ key: 'manage', label: '管理', className: 'action-link--primary' });
      }
      if ((row.isPermission && row.status != 2 && !row.published) || (row.isPermission && !row.enabled)) {
        actions.push({ key: 'delete', label: '删除', className: 'action-link--danger' });
      }
      // 更多里的动作
      if (row.isPermission && row.published) {
        actions.push({ key: 'copy', label: '复制', className: 'action-link--primary' });
        actions.push({ key: 'toggleEnable', label: row.enabled ? '停用' : '启用', className: 'action-link--primary' });
        if (this.showSetTopFeature) {
          actions.push({ key: 'toggleTop', label: row.isTop ? '取消置顶' : '置顶', className: 'action-link--primary' });
        }
      }
      return actions;
    },
    getInlineActions(row) {
      const actions = this.buildActions(row);
      return actions.slice(0, 4);
    },
    getDropdownActions(row) {
      const actions = this.buildActions(row);
      return actions.length > 4 ? actions.slice(4) : [];
    }
    ,
    // 按已选标签宽度动态调整“授课教师”选择框宽度
    adjustTeacherWidth() {
      this.$nextTick(() => {
        const select = this.$refs.teacherSelect;
        this.adjustSelectWidth(select, 200, 800, 60);
      });
    },
    // 按已选标签宽度动态调整“创建人”选择框宽度
    adjustCreatorWidth() {
      this.$nextTick(() => {
        const select = this.$refs.creatorSelect;
        this.adjustSelectWidth(select, 200, 800, 60);
      });
    },
    // 通用：累加 el-select__tags 内所有 tag 的宽度，设置选择框宽度
    adjustSelectWidth(selectRef, min = 200, max = 800, extra = 0) {
      if (!selectRef || !selectRef.$el) return;
      const el = selectRef.$el;
      const tags = Array.from(el.querySelectorAll('.el-select__tags .el-tag'));
      const inputInner = el.querySelector('.el-input__inner');
      const padding = 24; // 预留箭头/输入余量
      const tagsWidth = tags.reduce((sum, tag) => sum + (tag.getBoundingClientRect().width || 0), 0);
      const target = Math.max(min, Math.min(tagsWidth + padding + extra, max));
      el.style.width = `${target}px`;
      if (inputInner) {
        inputInner.style.width = `${target}px`;
      }
    },
    // AI 播放器相关方法
    getLanguageName(lang) {
      const item = (this.selectAllLang || []).find(it => it.srclang === lang);
      return (item && item.label) || '';
    },
    handleSelectionChange(val) {
      this.selectedCourses = val || [];
    },
    getAIInfoByList(list = []) {
      const total = list.length;
      let aiSetNum = 0;
      let aiSetNoNum = 0;
      list.forEach(item => {
        if (item.aiSet === 1) {
          aiSetNum++;
        } else {
          aiSetNoNum++;
        }
      });
      return {
        selectNum: total,
        aiSetNum,
        aiSetNoNum
      };
    },
    setAI(row) {
      this.aiSetting = {
        dlgShow: true,
        ...row
      };
    },
    changeAIKey(key) {
      this.aiSetting[key] = this.aiSetting[key] === 1 ? 0 : 1;
    },
    confirmAISetting() {
      const item = deepCopy(this.aiSetting);
      item.languageStatus = item.aiSet;
      item.languageCode = item.languageCode || [];
      if (!item.languageCode.includes('zh-CN')) {
        item.languageCode.unshift('zh-CN');
      }
      this._benchAiSet(
        [item],
        () => {
          this.$showManageMessage('AI设置保存成功', 'success');
          this.aiSetting.dlgShow = false;
          this.searchData();
        },
        () => {
          this.$showManageMessage('AI设置保存失败！', 'error');
        }
      );
    },
    setLanguage() {
      if (!this.selectedCourses.length) return;
      const info = this.getAIInfoByList(this.selectedCourses);
      this.languageSetting = {
        dlgShow: true,
        languageCode: ['zh-CN', 'en-US'],
        ...info
      };
    },
    enableAI() {
      if (!this.selectedCourses.length) return;
      const info = this.getAIInfoByList(this.selectedCourses);
      this.aiProcessSetting = {
        dlgShow: true,
        aiSet: 1,
        aiAbstract: 1,
        aiDraft: 1,
        languageCode: ['zh-CN', 'en-US'],
        ...info
      };
    },
    confirmLanguageSetting() {
      const courseList = deepCopy(this.selectedCourses || []);
      let languageCode = deepCopy(this.languageSetting.languageCode || []);
      if (!languageCode.includes('zh-CN')) {
        languageCode.unshift('zh-CN');
      }
      courseList.forEach(item => {
        item.languageCode = languageCode;
        item.aiTranslate = item.aiSet;
        item.languageStatus = item.aiSet;
      });
      this._benchAiSet(
        courseList,
        () => {
          this.$showManageMessage('设置语种成功！', 'success');
          this.languageSetting.dlgShow = false;
          this.searchData();
        },
        () => {
          this.$showManageMessage('设置语种失败！', 'error');
        }
      );
    },
    confirmAiProcess() {
      const courseList = deepCopy(this.selectedCourses || []);
      let { aiSet, aiAbstract, aiDraft, languageCode } = this.aiProcessSetting;
      languageCode = languageCode || [];
      if (!languageCode.includes('zh-CN')) {
        languageCode.unshift('zh-CN');
      }
      courseList.forEach(item => {
        item.aiSet = aiSet;
        item.aiAbstract = aiAbstract;
        item.aiDraft = aiDraft;
        item.aiTranslate = aiSet;
        item.languageStatus = aiSet;
        item.languageCode = languageCode;
      });
      this._benchAiSet(
        courseList,
        () => {
          this.$showManageMessage('开启AI处理成功！', 'success');
          this.aiProcessSetting.dlgShow = false;
          this.searchData();
        },
        () => {
          this.$showManageMessage('开启AI处理失败！', 'error');
        }
      );
    },
    _benchAiSet(courseList, successCB, failCB) {
      apiCourse.benchAiSet({ courseList }).then(res => {
        if (res && res.status === 200) {
          if (successCB) successCB(res);
        } else if (failCB) {
          failCB(res);
        }
      });
    },
    getAiPermission() {
      apiCourse.listByUser({}).then(res => {
        console.log('res', res);
        if(res.code === 200){
          let index = res.data.findIndex(item => item.permissionCode === 'KjbAiSetCode');
          this.aiPermission = index !== -1;
           console.log('index', index, this.aiPermission);
        }
      })
    }
  }
};
</script>

<style lang="scss" scoped>
#app::-webkit-scrollbar {
  width: 6px;
  height: 8px;
}

#app::-webkit-scrollbar-thumb {
  border-radius: 6px;
  background-color: rgb(78, 166, 255);
}

.noSplitDatePicker {

  /* 初始隐藏范围选择器的分隔符与关闭图标 */
  ::v-deep .el-range-separator,
  ::v-deep .el-range__close-icon {
    display: none !important;
  }
}

// .resetDatePicker {
//   ::v-deep .el-date-editor {
//     width: 250px;
//   }
// }

.sou {
  padding: 0 0 0 0px !important;
}

.el-col {
  padding: 0 0 0 10px !important;
}

.table-wrapper {
  padding: 16px;
  background-color: #ffffff;
  margin-top: 10px;
  border-radius: 6px;
}

.grid-content {
  padding-right: 0px;
}

.org-name-cell {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.el-button--text {
  font-size: 14px;
}

.filter-wrapper {
  padding: 16px;
  background-color: #ffffff;
  border-radius: 6px;
}

.filter-row {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  // margin-bottom: 10px;
}

.filter-fields {
  display: flex;
  flex-wrap: wrap;
}

.filter-field {
  margin-right: 10px;
  margin-bottom: 0;
}

.filter-row--advanced {
  margin-top: 10px;
}

.toggle-link {
  padding: 0;
  font-size: 14px;
  color: #4284F7;
}

.option-code {
  margin-left: 4px;
  color: #999;
}

.teacher-filter {
  ::v-deep .choice {
    width: 100%;
  }
}
.creator-filter {
  ::v-deep .choice {
    width: 100%;
  }
}

.filter-actions--inline {
  padding-top: 0;
}

.filter-actions .el-button+.el-button {
  margin-left: 10px;
}

.filter-actions {
  display: flex;
  align-items: center;
}

.filter-actions .icon-btn+.icon-btn {
  margin-left: 8px;
}

.filter-actions .toggle-link {
  margin-right: 10px;
}

.icon-btn {
  width: 32px;
  height: 32px;
  cursor: pointer;
  background-repeat: no-repeat;
  background-position: center;
  background-size: 32px 32px;
  background-color: transparent;
  // transition: all 0.2s ease;
}

.icon-btn:disabled {
  cursor: not-allowed;
  opacity: 0.6;
}

.icon-btn--search {
  background-image: url('~@/assets/images/svg/search_active.svg');
}

.icon-btn--reset {
  background-image: url('~@/assets/images/svg/reset.svg');
  background-size: 15px 15px;
}

.icon-btn--reset:hover,
.icon-btn--reset:active {
  background-image: url('~@/assets/images/svg/reset_active.svg');
  background-size: 32px 32px;
}

.icon-btn--top {
  background-image: url('~@/assets/images/svg/pintotop.svg');
  background-size: 14px 14px;
}

.icon-btn--top:hover,
.icon-btn--top:active {
  background-image: url('~@/assets/images/svg/pintotop_active.svg');
  background-size: 32px 32px;
}

.icon-btn--export {
  background-image: url('~@/assets/images/svg/export.svg');
  background-size: 14px 14px;
}

.icon-btn--export:hover,
.icon-btn--export:active {
  background-image: url('~@/assets/images/svg/export_active.svg');
  background-size: 32px 32px;

}

.icon-btn.is-disabled {
  cursor: not-allowed;
  opacity: 0.6;
  pointer-events: none;
}

.filter-extra-actions {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  padding-bottom: 20px;
}

.filter-extra-actions .icon-btn,
.filter-extra-actions .create-course-btn {
  margin-right: 10px;
}

.create-course-btn {
  width: 120px;
  height: 32px;
  padding-left: 36px;
  padding-right: 16px;
  border-radius: 6px;
  border: 1px solid #4284F7;
  background-color: #ffffff;
  background-image: url('~@/assets/images/svg/createCourse.svg');
  background-repeat: no-repeat;
  background-position: 12px center;
  background-size: 14px 14px;
  color: #4284F7;
  font-weight: 400;
  font-size: 14px;
  line-height: 32px;
  cursor: pointer;
  transition: all 0.2s ease;
}

.create-course-btn:hover,
.create-course-btn:active {
  background-color: #4284F7;
  border-color: transparent;
  color: #ffffff;
  background-image: url('~@/assets/images/svg/createCourse_active.svg');
}

.toggle-link {
  padding: 0;
}

/* 移除右对齐，保持左侧布局 */
::v-deep .el-table .el-table__body-wrapper::-webkit-scrollbar {
  display: block;
}

.advanced-filter {
  margin-top: 10px;
}

// .learning-time-range .el-date-editor {
//   width: 250px;
// }

.pagination {
  text-align: right;
  padding-top: 20px;
  ::v-deep .el-pagination {
    .el-pagination__total {
      font-size: 14px;
      color: #000000;
    }
    .el-pagination__sizes {
      margin-right: 4px;
      .el-input{
        margin: 0;
        width: 89px;
        
      }
      .el-input__inner {
        width: 89px;
        background: #F5F9FF;
        border-radius: 4px;
        border: 1px solid #DFDFDF;
        height: 28px;
        font-size: 14px;
        color: #000000;
      }
    }
    .btn-prev, .btn-next {
      width: 28px;
      height: 28px;
      background: #F5F9FF;
      border-radius: 4px;
      border: 1px solid #DFDFDF;
      // &:hover {
      //   background: #4284F7;
      //   color: #FFFFFF;
      // }
    }
    .btn-quicknext{
      background: transparent;
      border: none;
      line-height: 44px;
      &:before {
        content: '......';
      }
  
    }
    .el-pager {
      .number {
        min-width: 28px;
        height: 28px;
        background: #F5F9FF;
        border-radius: 4px;
        border: 1px solid #DFDFDF;
        font-weight: normal;
        color: #000000;
        margin: 0 4px;
        &.active {
          background: #4284F7;
          color: #FFFFFF;
          border: none;
        }
      }
    }
    .el-pagination__jump {
      font-size: 14px;
      color: #000000;
      margin-left: 4px;
      .el-input__inner {
        min-width: 28px;
        height: 28px;
        background: #F5F9FF;
        border-radius: 4px;
        border: 1px solid #DFDFDF;
        font-size: 14px;
        color: #000000;
      }
    }

  }
}

.course-types {
  display: flex;
  justify-content: center;
  padding: 15px;

  .course-type {
    margin: 10px;
    text-align: center;
    padding: 5px;
    cursor: pointer;

    img {
      width: 110px;
      height: 110px;
    }

    .info {
      padding-top: 10px;
    }
  }

  .choose {
    border: 2px solid #008000;
  }
}

.el-aside {
  padding: 5px 10px;
}

.cctree {
  .cctree-chapter {
    .cctree-chapter-name {
      border-bottom: 1px solid #dddddd;
    }

    .cctree-chapter-cells {
      margin: 0px;
      list-style-type: circle;
      padding: 0px;

      .cctree-chapter-cell {
        line-height: 30px;
        list-style-type: circle;
        padding-left: 25px;
      }
    }
  }
}

.el-dialog__body {
  overflow: hidden;
}

// AI 播放器相关样式
.form-item {
  margin-bottom: 20px;
  display: flex;
  align-items: center;
  gap: 10px;
}

.form-label {
  white-space: nowrap;
  font-size: 14px;
  color: #000000;
}

.status-text {
  font-size: 14px;
  color: #000000;
}

.tips {
  color: #f56c6c;
  font-size: 12px;
  margin: 10px 0;
  line-height: 1.5;
}

.languages-list {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
}

.language-tag {
  display: inline-block;
  padding: 4px 12px;
  border-radius: 4px;
  background-color: #f5f5f5;
  font-size: 12px;
}

// 注意：custom-putaway 和 custom-takeout 已在全局样式 src/assets/styles/btn.scss 中定义
// 无需在此重复定义

::v-deep .el-table .el-table__body-wrapper::-webkit-scrollbar-thumb {
  border-radius: 4px;
  background-color: #4284F7;
}

::v-deep .el-table .el-table__body-wrapper::-webkit-scrollbar {
  width: 6px;
  height: 6px;
  background-color:rgba(0, 0, 0, .1);
  border-radius: 4px;
}

::v-deep .el-table .el-table__body-wrapper::-webkit-scrollbar-thumb {
  border-radius: 4px;
  background-color: #4284F7
}

::v-deep .el-table__empty-block {
  width: 100% !important;
  display: flex;
  justify-content: center;
  align-items: center;
}

::v-deep.el-table {
  border-radius: 6px 6px 0 0;
  td.el-table__cell {
    border-bottom: 1px solid rgba(0, 0, 0, .1);
  }
  th.el-table__cell {
    background: rgba(66, 132, 247, 0.1);
    padding: 3px 0;

    .cell {
      font-weight: bold;
      font-size: 14px;
      color: #60769D;
    }
    .caret-wrapper {
      .sort-caret {
        border: 4px solid transparent;
        &.ascending {
          border-bottom-color: #C0C4CC;
          top: 8px;
        }
        &.descending {
          border-top-color: #C0C4CC;
          bottom: 8px;
        }
      }
    }
    &.ascending .sort-caret.ascending {
      border-bottom-color: #409EFF;
    }
    &.descending .sort-caret.descending{
      border-top-color: #409EFF;
    }

    &.el-table--medium .el-table__cell {
      padding: 5px 0;
    }
  }

  .course-name {
    font-weight: 400;
    font-size: 14px;
    color: #000000;
    line-height: 20px;
  }

  .common-cell {
    font-weight: 400;
    font-size: 14px;
    color: #000000;
  }
  .common-cell-right {
    padding-right: 20px;
  }

  .single-line-ellipsis {
    display: inline-block;
    max-width: 100%;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    vertical-align: middle;
  }

  .status--pass {
    color: #2EAD4D;
  }

  .status--reject {
    color: #F41228;
  }
  .status--audit {
    color: #FF9900;
  }

  .action-link--primary {
    color: #4284F7;
    font-weight: bold;
  }

  .action-link--danger {
    color: #E32E2E;
    font-weight: bold;
  }

  .action-link--more {
    color: #999999;
    font-weight: bold;
    .el-icon-arrow-down {
      font-weight: bold;
    }
  }

  .action-link--bold {
    font-weight: bold;
  }

  ::v-deep .el-table--medium .el-table__cell {
    padding: 5px 0;
  }
}
.qrcode-img {
  width: 150px;
  height: 150px;
  display: block;
  position: relative;
  .downloadn-container {
    position: absolute;
    width: 40px;
    height: 45px;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    z-index: 99;
    background: white;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    transition: all 0.3s ease;
    box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
    cursor: pointer;
    span {
      color: #409eff;
      display: block;
      font-size: 12px;
      line-height: 12px;
    }
  }
}
</style>

<style lang="scss">
.filter-field--name {
  .el-input__inner {
    width: 444px;
    height: 32px;
    background: #FFFFFF;
    border-radius: 6px;
    border: 1px solid rgba(0, 0, 0, .2);
    line-height: 32px;
    padding: 0 15px 0 10px;
    &:focus {
      border-color: #4284F7;
    }
  }
}

.filter-field--category  {
  .el-cascader {
    line-height: 32px;
    .el-input__inner {
      width: 180px;
      height: 32px;
      background: #FFFFFF;
      border-radius: 6px;
      border: 1px solid rgba(0, 0, 0, .2);
      line-height: 32px;
      padding: 0 15px 0 10px;
      color: #000000;
      &:focus {
        border: 1px solid #4284F7;
      }
    }

    .el-input {
      line-height: 32px;
      &.is-focus .el-input__inner{
        border-color: #4284F7;
      }
    }

    .el-input__suffix {
      line-height: 32px;
    }

    .el-input__icon {
      line-height: 32px;
    }
  }
  
  
}

.filter-field--teacher {
  .el-select {
    .el-select__input {
      margin-left: 10px;
    }
    .el-input__inner {
      min-width: 180px;
      width: auto;
      height: 32px;
      background: #FFFFFF;
      border-radius: 6px;
      border: 1px solid rgba(0, 0, 0, .2);
      line-height: 32px;
      padding: 0 15px 0 10px;
    }
    .el-input {
      &.is-focus .el-input__inner{
        border-color: #4284F7;
      }
    }
  }
}

.filter-field--status {
  .el-select {
    .el-select__input {
      margin-left: 10px;
    }

    .el-input__inner {
      width: 136px;
      height: 32px;
      background: #FFFFFF;
      border-radius: 6px;
      border: 1px solid rgba(0, 0, 0, .2);
      line-height: 32px;
      padding: 0 15px 0 10px;
      &.is-focus .el-input__inner{
        border-color: #4284F7;
      }
    }

    .el-input__icon {
      line-height: 32px;
    }
  }
}

.filter-field--publish {
  .el-select {
    .el-select__input {
      margin-left: 10px;
    }

    .el-input__inner {
      width: 136px;
      height: 32px;
      background: #FFFFFF;
      border-radius: 6px;
      border: 1px solid rgba(0, 0, 0, .2);
      line-height: 32px;
      padding: 0 15px 0 10px;
      &.is-focus .el-input__inner{
        border-color: #4284F7;
      }
    }

    .el-input__icon {
      line-height: 32px;
    }
  }
}

.filter-field--enabled {
  .el-select {
    .el-select__input {
      margin-left: 10px;
    }

    .el-input__inner {
      width: 136px;
      height: 32px;
      background: #FFFFFF;
      border-radius: 6px;
      border: 1px solid rgba(0, 0, 0, .2);
      line-height: 32px;
      padding: 0 15px 0 10px;
      &.is-focus .el-input__inner{
        border-color: #4284F7;
      }
    }

    .el-input__icon {
      line-height: 32px;
    }
  }
  
}

.filter-field--open {
  .el-select {
    .el-select__input {
      margin-left: 10px;
    }

    .el-input__inner {
      width: 124px;
      height: 32px;
      background: #FFFFFF;
      border-radius: 6px;
      border: 1px solid rgba(0, 0, 0, .2);
      line-height: 32px;
      padding: 0 15px 0 10px;
      &.is-focus .el-input__inner{
        border-color: #4284F7;
      }
    }

    .el-input__icon {
      line-height: 32px;
    }
  }
}

.filter-field--resowner {
  .el-cascader {
    min-width: 200px;
    width: auto;
    line-height: 32px;
    .el-input__inner {
      min-width: 200px;
      width: auto;
      height: 32px;
      background: #FFFFFF;
      border-radius: 6px;
      border: 1px solid rgba(0, 0, 0, .2);
      line-height: 32px;
      padding: 0 15px 0 10px;
      &:focus {
        border-color: #4284F7;
      }
    }
    &.is-focus .el-input__inner {
      border-color: #4284F7;
    }
  }
  .el-input {
    .el-input__inner {
      min-width: 200px;
      width: auto;
      height: 32px;
      background: #FFFFFF;
      border-radius: 6px;
      border: 1px solid rgba(0, 0, 0, .2);
      line-height: 32px;
      padding: 0 15px 0 10px;
    }
  }
}

.filter-field--creator {
  .el-select {
    min-width: 180px;
    width: auto;
    .el-select__input {
      margin-left: 10px;
    }

    .el-input__inner {
      min-width: 180px;
      width: auto;
      height: 32px;
      background: #FFFFFF;
      border-radius: 6px;
      border: 1px solid rgba(0, 0, 0, .2);
      line-height: 32px;
      padding: 0 15px 0 10px;
      &.is-focus .el-input__inner{
        border-color: #4284F7;
      }
    }
  }
  
}

.filter-field--create-from {
  .el-select {
    .el-select__input {
      margin-left: 10px;
    }

    .el-input__inner {
      width: 136px;
      height: 32px;
      background: #FFFFFF;
      border-radius: 6px;
      border: 1px solid rgba(0, 0, 0, .2);
      line-height: 32px;
      padding: 0 15px 0 10px;
      &.is-focus .el-input__inner{
        border-color: #4284F7;
      }
    }

    .el-input__icon {
      line-height: 32px;
    }
  }
  
}

.filter-field--time {
  .el-input__inner {
    width: 316px;
    height: 32px;
    background: #FFFFFF;
    border-radius: 6px;
    border: 1px solid rgba(0, 0, 0, .2);
    line-height: 32px;
    padding: 0 15px 0 10px;

    .el-input__icon {
      line-height: 32px;

      &.el-icon-date {
        position: absolute;
        right: 0;
      }

      &.el-icon-close {
        margin-right: 8px;
      }
    }
    .el-range-editor {
      .is-active:hover{
        border-color: #4284F7;
      }
    }
    .el-range-separator {
      line-height: 30px;
    }

    .el-range-input {
      line-height: 30px;
    }
  }
  .noSplitDatePicker {
    .el-range-input {
      text-align: left;
    }
  }
}

.icon-btn-tooltip {
  height: 30px;
  background: rgba(0, 0, 0, 1);
  border-radius: 15px;
  padding: 0 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  line-height: 30px;
  .popper__arrow {
    display: none !important;
  }
  .el-tooltip__popper__arrow {
    display: none !important;
  }
}
</style>

