|
|
@@ -414,30 +414,39 @@
|
|
|
<el-button type="primary" @click="choosePicVisible = false">{{ lang.ssConfirm }}</el-button>
|
|
|
</span>
|
|
|
</el-dialog>
|
|
|
- <el-dialog :title="lang.SelectWebImage" :visible.sync="sysPicVisible2" :append-to-body="true" width="710px"
|
|
|
- :before-close="handleClose" class="dialog_diy">
|
|
|
- <div>
|
|
|
- <div class="people_top_right" style="display: flex;align-items: center;">
|
|
|
- <div style="position: relative; width: 100%;">
|
|
|
- <el-input style="height: 100%" :placeholder="lang.ssSearchImageKey" v-model="searchImageValue"
|
|
|
- @keyup.enter.native="resetImage()"></el-input>
|
|
|
- <div class="search_img" @click="resetImage" style="right: 10px;">
|
|
|
- <img src="../../../assets/icon/search.png" alt />
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <el-button type="primary" size="default" style="margin-left: 10px;" @click="changePicture">{{ lang.ssChangeGrp
|
|
|
- }}</el-button>
|
|
|
+ <div class="web-search-modal" v-if="sysPicVisible2">
|
|
|
+ <div class="modal-overlay"></div>
|
|
|
+ <div class="modal-content web-search-content">
|
|
|
+ <div class="modal-header">
|
|
|
+ <h3 class="modal-title">{{ lang.ssWebSearchImage }}</h3>
|
|
|
+ <div class="modal-close" @click="sysPicVisible2 = false">×</div>
|
|
|
</div>
|
|
|
- <div class="sysPicBox" v-loading="imageloading">
|
|
|
- <div class="picNone" v-if="!imageList.length">
|
|
|
- {{ lang.ssEnterKeywordSearch }}
|
|
|
+ <div class="modal-body web-search-body">
|
|
|
+ <div class="search-section">
|
|
|
+ <label class="search-label">{{ lang.ssSearchKeyword }}</label>
|
|
|
+ <div style="position: relative; width: 100%;">
|
|
|
+ <el-input class="search_input" style="height: 40px; border-radius: 4px;" :placeholder="lang.ssSearchImageKey" v-model="searchImageValue"
|
|
|
+ @keyup.enter.native="resetImage()"></el-input>
|
|
|
+ <div class="search_img" @click="resetImage" style="right: 10px;">
|
|
|
+ <img src="../../../assets/icon/search.png" alt />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- <div v-for="(sys, sysIndex) in imageList" :key="sysIndex" class="sysPic">
|
|
|
- <img :src="sys.url" alt="" @click="chooseSysPic2(sys.url)" />
|
|
|
+ <div class="image-grid" v-loading="imageloading">
|
|
|
+ <div class="picNone" v-if="!imageList.length && !imageloading">
|
|
|
+ {{ lang.ssEnterKeywordSearch }}
|
|
|
+ </div>
|
|
|
+ <div v-for="(sys, sysIndex) in imageList" :key="sysIndex" class="image-item">
|
|
|
+ <img :src="sys.url" alt="" @click="chooseSysPic2(sys.url)" />
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
+ <div class="modal-footer web-search-footer">
|
|
|
+ <button class="btn-cancel" @click="sysPicVisible2 = false">{{ lang.ssCancel }}</button>
|
|
|
+ <button class="btn-confirm" @click="changePicture">{{ lang.ssChangeGrp }}</button>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- </el-dialog>
|
|
|
+ </div>
|
|
|
<InteractiveToolDialog ref="InteractiveToolDialogRef" @addTool="addTool" />
|
|
|
<VideoUploadDialog ref="VideoUploadDialogRef" @uploadLocalVideo="handleLocalVideoUpload"
|
|
|
@uploadProgress="handleUploadProgress" @searchBilibili="handleBilibiliSearch" />
|
|
|
@@ -761,7 +770,7 @@
|
|
|
<div class="modal-overlay"></div>
|
|
|
<div class="modal-content publish-modal-content">
|
|
|
<div class="modal-header">
|
|
|
- <h3 class="modal-title">发布课程</h3>
|
|
|
+ <h3 class="modal-title">{{ lang.ssPublishCourse }}</h3>
|
|
|
<div class="modal-close" @click="dialogVisiblePublish = false">×</div>
|
|
|
</div>
|
|
|
<div class="modal-body publish-modal-body">
|
|
|
@@ -777,8 +786,8 @@
|
|
|
<div class="form-box-left">
|
|
|
<div class="form-row">
|
|
|
<div class="form-item required" style="flex: 2;">
|
|
|
- <label class="form-label">学科</label>
|
|
|
- <el-select v-model="selectedSubject" placeholder="请选择学科" class="custom-select" collapse-tags multiple
|
|
|
+ <label class="form-label">{{ lang.ssSubjectCategory }}</label>
|
|
|
+ <el-select v-model="selectedSubject" :placeholder="lang.ssSelectSubj" class="custom-select" collapse-tags multiple
|
|
|
style="width: 100%">
|
|
|
<el-option v-for="option in subjectOptions" :key="option.id" :label="option.name"
|
|
|
:value="option.id"></el-option>
|
|
|
@@ -788,8 +797,8 @@
|
|
|
|
|
|
<div class="form-row">
|
|
|
<div class="form-item required">
|
|
|
- <label class="form-label">年级</label>
|
|
|
- <el-select v-model="selectedGrade" placeholder="请选择年级" class="custom-select" collapse-tags multiple
|
|
|
+ <label class="form-label">{{ lang.ssGradeType }}</label>
|
|
|
+ <el-select v-model="selectedGrade" :placeholder="lang.ssSelectGrade" class="custom-select" collapse-tags multiple
|
|
|
style="width: 100%">
|
|
|
<el-option v-for="option in gradeOptions" :key="option.id" :label="option.name"
|
|
|
:value="option.id"></el-option>
|
|
|
@@ -797,8 +806,8 @@
|
|
|
</div>
|
|
|
|
|
|
<div class="form-item required">
|
|
|
- <label class="form-label">班级</label>
|
|
|
- <el-select v-model="checkboxList2" placeholder="请选择班级" class="custom-select" collapse-tags multiple
|
|
|
+ <label class="form-label">{{ lang.ssClass }}</label>
|
|
|
+ <el-select v-model="checkboxList2" :placeholder="lang.ssSelectClass" class="custom-select" collapse-tags multiple
|
|
|
style="width: 100%">
|
|
|
<el-option v-for="option in classOptions" :key="option.id" :label="option.name"
|
|
|
:value="option.id"></el-option>
|
|
|
@@ -808,15 +817,15 @@
|
|
|
|
|
|
<div class="form-row">
|
|
|
<div class="form-item required">
|
|
|
- <label class="form-label">可见范围</label>
|
|
|
+ <label class="form-label">{{ lang.ssVisibilityRange }}</label>
|
|
|
<div class="radio-group">
|
|
|
<div class="radio-item" :class="{ active: !isTeacherSee }" @click="isTeacherSee = false">
|
|
|
<div class="custom-radio">
|
|
|
<div class="radio-inner" :class="{ checked: !isTeacherSee }"></div>
|
|
|
</div>
|
|
|
<div>
|
|
|
- <label>仅发布学生可见</label>
|
|
|
- <div class="radio-desc">仅对发布的班级学生可见,其他人无法访问</div>
|
|
|
+ <label>{{ lang.ssOnlyStudentsVisible }}</label>
|
|
|
+ <div class="radio-desc">{{ lang.ssOnlyStudentsDesc }}</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="radio-item" :class="{ active: isTeacherSee }" @click="isTeacherSee = true">
|
|
|
@@ -824,8 +833,8 @@
|
|
|
<div class="radio-inner" :class="{ checked: isTeacherSee }"></div>
|
|
|
</div>
|
|
|
<div>
|
|
|
- <label>组织可见</label>
|
|
|
- <div class="radio-desc">学校内所有教师均可查看</div>
|
|
|
+ <label>{{ lang.ssOrganizationVisible }}</label>
|
|
|
+ <div class="radio-desc">{{ lang.ssOrganizationDesc }}</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
@@ -836,16 +845,16 @@
|
|
|
<button class="btn-publish" @click="confirmPublish">
|
|
|
<!-- <i class="el-icon-loading" v-if="publishing"></i>
|
|
|
<i class="el-icon-right" v-else></i> -->
|
|
|
- 确认发布
|
|
|
+ {{ lang.ssConfirmPublish }}
|
|
|
</button>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="form-box-right">
|
|
|
<div class="form-row">
|
|
|
<div class="form-item" style="flex: 1;">
|
|
|
- <label class="form-label">课程封面</label>
|
|
|
- <div class="cover-upload-area" @click="choosePicVisible = true" v-if="!cover.length">
|
|
|
- <div class="cover-placeholder">
|
|
|
+ <label class="form-label">{{ lang.ssCourseCover }}</label>
|
|
|
+ <div class="cover-upload-area" v-loading="avatar_loading">
|
|
|
+ <div class="cover-placeholder" v-if="!cover.length">
|
|
|
<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
|
<g id="Component 2">
|
|
|
<path id="Vector"
|
|
|
@@ -857,15 +866,36 @@
|
|
|
<path id="Vector_3" d="M42 30L32 20L10 42" stroke="#D1D5DB" stroke-width="4" />
|
|
|
</g>
|
|
|
</svg>
|
|
|
- <span>点击选择上传方式</span>
|
|
|
+ <span>{{ lang.ssHoverToSelectUpload }}</span>
|
|
|
</div>
|
|
|
- </div>
|
|
|
- <div v-else class="cover-preview" @click="choosePicVisible = true"
|
|
|
- :class="{ uploadFm2: cover.length }">
|
|
|
- <img :src="cover[0].url" alt="" class="cover_p" />
|
|
|
- <div class="cover_mask">
|
|
|
- <img src="../../../assets/icon/new/cover_update.png" /><span style="margin-top:5px;">{{
|
|
|
- lang.ssModifyCover }}</span>
|
|
|
+ <div class="cover-preview" v-else>
|
|
|
+ <img :src="cover[0].url" alt="" class="cover_p" />
|
|
|
+ </div>
|
|
|
+ <div class="upload-options">
|
|
|
+ <div class="option-item" @click="uploadFromLocal($event)">
|
|
|
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
|
+ <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
|
|
|
+ <polyline points="17 8 12 3 7 8"/>
|
|
|
+ <line x1="12" y1="3" x2="12" y2="15"/>
|
|
|
+ </svg>
|
|
|
+ <span>{{ lang.ssUploadFromLocal }}</span>
|
|
|
+ <input type="file" accept="image/*" style="display: none" @change="beforeUpload1" />
|
|
|
+ </div>
|
|
|
+ <div class="option-item" @click="searchFromWeb">
|
|
|
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
|
+ <circle cx="11" cy="11" r="8"/>
|
|
|
+ <path d="M21 21l-4.35-4.35"/>
|
|
|
+ </svg>
|
|
|
+ <span>{{ lang.ssSearchFromWeb }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="option-item" @click="generateFromAI">
|
|
|
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
|
+ <path d="M12 2L2 7l10 5 10-5-10-5z"/>
|
|
|
+ <path d="M2 17l10 5 10-5"/>
|
|
|
+ <path d="M2 12l10 5 10-5"/>
|
|
|
+ </svg>
|
|
|
+ <span>{{ lang.ssGenerateFromAI }}</span>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
@@ -1113,6 +1143,7 @@ export default {
|
|
|
selectedGrade: [],
|
|
|
subjectOptions: [],
|
|
|
gradeOptions: [],
|
|
|
+ avatar_loading: false,
|
|
|
};
|
|
|
},
|
|
|
directives: {
|
|
|
@@ -1337,6 +1368,64 @@ export default {
|
|
|
this.nextSteps();
|
|
|
// this.$message.success('课程发布成功');
|
|
|
},
|
|
|
+ // 自本地上传
|
|
|
+ uploadFromLocal(e) {
|
|
|
+ console.log('自本地上传');
|
|
|
+ var el = e.currentTarget;
|
|
|
+ el.getElementsByTagName("input")[0].click();
|
|
|
+ e.target.value = "";
|
|
|
+ },
|
|
|
+ // 自网页搜索
|
|
|
+ searchFromWeb() {
|
|
|
+ console.log('自网页搜索');
|
|
|
+ // 触发现有的网页搜索功能
|
|
|
+ this.searchImageValue = this.courseName;
|
|
|
+ this.resetImage();
|
|
|
+ },
|
|
|
+ // 自AI生成
|
|
|
+ generateFromAI() {
|
|
|
+ console.log('自AI生成');
|
|
|
+ if(!this.courseName){
|
|
|
+ this.$message.error(this.lang.ssFillCourseName);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if(this.avatar_loading){
|
|
|
+ this.$message.error(this.lang.xiaokeloading);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.avatar_loading = true;
|
|
|
+ const prompt = [
|
|
|
+ {
|
|
|
+ role: "user",
|
|
|
+ content: `你是一名一流的UI设计师,现在你需要为这个场景设计相应的图标:
|
|
|
+ 「${this.courseName}」
|
|
|
+ 请给出3个不同的设计方案。
|
|
|
+ ## 要求 在你给出的设计方案中,坚持同时满足以下要求
|
|
|
+ 0. 要求体现学科特点 或者教学特点。
|
|
|
+ 1. 背景底色为白色,正方形画面,画面填充满内容。
|
|
|
+ 2. 采用扁平化的设计风格
|
|
|
+ 3.不要在设计中设计到相关的文字,不如这个描述不允许类似这样的描述“繁体中文的“文”字,突出语言特色。”。
|
|
|
+ ## 输出一个json格式的回复,输出格式如下:
|
|
|
+ {"option":["方案一 核心视觉元素(2个):xxx 辅助视觉元素(1-3个):xxxx 核心情绪:xxx 主体颜色:xxx设计风格:xxxx 整体构图与画面内容:xxxx","方案二......","方案三......"]}`,
|
|
|
+ },
|
|
|
+ ];
|
|
|
+ this.chat_no_stream(prompt, { type: "json_object" }).then((res) => {
|
|
|
+ console.log(res);
|
|
|
+ let aimap = JSON.parse(res).option;
|
|
|
+ this.ai_generate_image(aimap[0]).then(
|
|
|
+ (res) => {
|
|
|
+ this.cover = [
|
|
|
+ {
|
|
|
+ name: res,
|
|
|
+ url: res,
|
|
|
+ uid: uuidv4()
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ this.avatar_loading = false;
|
|
|
+ }
|
|
|
+ );
|
|
|
+ });
|
|
|
+ },
|
|
|
closePan(tool) {
|
|
|
if (tool == 15) {
|
|
|
if (JSON.stringify(this.answerQ) == JSON.stringify(this.answerQ2)) {
|
|
|
@@ -2229,7 +2318,7 @@ export default {
|
|
|
_this.ajax
|
|
|
.post("https://gpt.cocorobo.cn/search_image", {
|
|
|
page: _this.ppage,
|
|
|
- pagesize: 9,
|
|
|
+ pagesize: 6,
|
|
|
query: _this.searchImageValue
|
|
|
})
|
|
|
.then(function (response) {
|
|
|
@@ -3762,11 +3851,9 @@ export default {
|
|
|
|
|
|
.picNone {
|
|
|
position: absolute;
|
|
|
- left: 50%;
|
|
|
- top: 45%;
|
|
|
- transform: translate(-50%, -50%);
|
|
|
- width: fit-content;
|
|
|
+ width: 100%;
|
|
|
color: #9c9c9c;
|
|
|
+ text-align: center;
|
|
|
}
|
|
|
|
|
|
.sysPic {
|
|
|
@@ -3804,6 +3891,10 @@ export default {
|
|
|
margin-bottom: 10px;
|
|
|
}
|
|
|
|
|
|
+.search_input >>> .el-input__inner{
|
|
|
+ padding: 0 30px 0 15px;
|
|
|
+}
|
|
|
+
|
|
|
.search_img {
|
|
|
width: 20px;
|
|
|
height: 20px;
|
|
|
@@ -3811,6 +3902,7 @@ export default {
|
|
|
right: 30px;
|
|
|
top: 50%;
|
|
|
transform: translateY(-50%);
|
|
|
+ cursor: pointer;
|
|
|
}
|
|
|
|
|
|
.search_img>img {
|
|
|
@@ -4884,6 +4976,7 @@ export default {
|
|
|
cursor: pointer;
|
|
|
transition: all 0.3s;
|
|
|
background: #fafbfc;
|
|
|
+ position: relative;
|
|
|
}
|
|
|
|
|
|
.cover-preview {
|
|
|
@@ -4920,6 +5013,48 @@ export default {
|
|
|
font-size: 12px;
|
|
|
}
|
|
|
|
|
|
+.upload-options {
|
|
|
+ position: absolute;
|
|
|
+ top: 50%;
|
|
|
+ left: 50%;
|
|
|
+ transform: translate(-50%, -50%);
|
|
|
+ background-color: white;
|
|
|
+ border-radius: 8px;
|
|
|
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
|
+ padding: 12px;
|
|
|
+ display: none;
|
|
|
+ z-index: 10;
|
|
|
+ min-width: 160px;
|
|
|
+}
|
|
|
+
|
|
|
+.cover-upload-area:hover .upload-options {
|
|
|
+ display: block;
|
|
|
+}
|
|
|
+
|
|
|
+.option-item {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ padding: 8px 12px;
|
|
|
+ border-radius: 4px;
|
|
|
+ cursor: pointer;
|
|
|
+ transition: all 0.3s;
|
|
|
+ margin-bottom: 4px;
|
|
|
+}
|
|
|
+
|
|
|
+.option-item:last-child {
|
|
|
+ margin-bottom: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.option-item:hover {
|
|
|
+ background-color: #fff4e5;
|
|
|
+ color: #f78b22;
|
|
|
+}
|
|
|
+
|
|
|
+.option-item svg {
|
|
|
+ margin-right: 8px;
|
|
|
+ width: 16px;
|
|
|
+}
|
|
|
+
|
|
|
.publish-modal-footer {
|
|
|
padding: 16px 0 0;
|
|
|
display: flex;
|
|
|
@@ -4949,4 +5084,110 @@ export default {
|
|
|
.btn-publish i {
|
|
|
margin-right: 8px;
|
|
|
}
|
|
|
+
|
|
|
+/* 网页搜索图片弹窗 */
|
|
|
+.web-search-modal {
|
|
|
+ position: fixed;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ right: 0;
|
|
|
+ bottom: 0;
|
|
|
+ z-index: 1001;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+}
|
|
|
+
|
|
|
+.web-search-content {
|
|
|
+ width: 710px;
|
|
|
+ background-color: white;
|
|
|
+ border-radius: 8px;
|
|
|
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
|
+ overflow: hidden;
|
|
|
+}
|
|
|
+
|
|
|
+.web-search-body {
|
|
|
+ padding: 24px;
|
|
|
+}
|
|
|
+
|
|
|
+.search-section {
|
|
|
+ margin-bottom: 20px;
|
|
|
+}
|
|
|
+
|
|
|
+.search-label {
|
|
|
+ display: block;
|
|
|
+ margin-bottom: 8px;
|
|
|
+ font-weight: 500;
|
|
|
+ color: #6B7280;
|
|
|
+}
|
|
|
+
|
|
|
+.image-grid {
|
|
|
+ display: grid;
|
|
|
+ grid-template-columns: repeat(3, 1fr);
|
|
|
+ gap: 15px;
|
|
|
+ /* margin-bottom: 20px; */
|
|
|
+ position: relative;
|
|
|
+}
|
|
|
+
|
|
|
+.image-item {
|
|
|
+ width: 100%;
|
|
|
+ aspect-ratio: 16 / 9;
|
|
|
+ overflow: hidden;
|
|
|
+ border-radius: 10px;
|
|
|
+ cursor: pointer;
|
|
|
+ transition: all 0.3s;
|
|
|
+}
|
|
|
+
|
|
|
+.image-item:hover {
|
|
|
+ transform: scale(1.02);
|
|
|
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
|
+}
|
|
|
+
|
|
|
+.image-item img {
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ object-fit: cover;
|
|
|
+}
|
|
|
+
|
|
|
+.web-search-footer {
|
|
|
+ padding: 16px 24px;
|
|
|
+ /* border-top: 1px solid #f0f0f0; */
|
|
|
+ display: flex;
|
|
|
+ justify-content: flex-end;
|
|
|
+ gap: 12px;
|
|
|
+}
|
|
|
+
|
|
|
+.web-search-footer .btn-cancel {
|
|
|
+ padding: 8px 16px;
|
|
|
+ border: 1px solid #dcdfe6;
|
|
|
+ border-radius: 10px;
|
|
|
+ background-color: white;
|
|
|
+ color: #606266;
|
|
|
+ cursor: pointer;
|
|
|
+ font-size: 14px;
|
|
|
+ transition: all 0.3s;
|
|
|
+ flex: 1;
|
|
|
+}
|
|
|
+
|
|
|
+.web-search-footer .btn-cancel:hover {
|
|
|
+ border-color: #c6e2ff;
|
|
|
+ color: #409eff;
|
|
|
+}
|
|
|
+
|
|
|
+.web-search-footer .btn-confirm {
|
|
|
+ background-color: #ff7d00;
|
|
|
+ border: 1px solid #ff7d00;
|
|
|
+ color: white;
|
|
|
+ padding: 10px 16px;
|
|
|
+ border-radius: 10px;
|
|
|
+ cursor: pointer;
|
|
|
+ font-size: 14px;
|
|
|
+ transition: all 0.3s;
|
|
|
+ font-weight: 500;
|
|
|
+ flex: 1;
|
|
|
+}
|
|
|
+
|
|
|
+.web-search-footer .btn-confirm:hover {
|
|
|
+ background-color: #e67300;
|
|
|
+}
|
|
|
</style>
|