Bläddra i källkod

修改课程模板

吴树波 2 veckor sedan
förälder
incheckning
255019ea67

+ 35 - 0
build/index.js

@@ -0,0 +1,35 @@
+const { run } = require('runjs')
+const chalk = require('chalk')
+const config = require('../vue.config.js')
+const rawArgv = process.argv.slice(2)
+const args = rawArgv.join(' ')
+
+if (process.env.npm_config_preview || rawArgv.includes('--preview')) {
+  const report = rawArgv.includes('--report')
+
+  run(`vue-cli-service build ${args}`)
+
+  const port = 9526
+  const publicPath = config.publicPath
+
+  var connect = require('connect')
+  var serveStatic = require('serve-static')
+  const app = connect()
+
+  app.use(
+    publicPath,
+    serveStatic('./dist', {
+      index: ['index.html', '/']
+    })
+  )
+
+  app.listen(port, function () {
+    console.log(chalk.green(`> Preview at  http://localhost:${port}${publicPath}`))
+    if (report) {
+      console.log(chalk.green(`> Report at  http://localhost:${port}${publicPath}report.html`))
+    }
+
+  })
+} else {
+  run(`vue-cli-service build ${args}`)
+}

+ 53 - 0
src/api/course/courseFinishTempParent.js

@@ -0,0 +1,53 @@
+import request from '@/utils/request'
+
+// 查询完课模板列表
+export function listCourseFinishTempParent(query) {
+  return request({
+    url: '/course/courseFinishTempParent/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询完课模板详细
+export function getCourseFinishTempParent(id) {
+  return request({
+    url: '/course/courseFinishTempParent/' + id,
+    method: 'get'
+  })
+}
+
+// 新增完课模板
+export function addCourseFinishTempParent(data) {
+  return request({
+    url: '/course/courseFinishTempParent',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改完课模板
+export function updateCourseFinishTempParent(data) {
+  return request({
+    url: '/course/courseFinishTempParent',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除完课模板
+export function delCourseFinishTempParent(id) {
+  return request({
+    url: '/course/courseFinishTempParent/' + id,
+    method: 'delete'
+  })
+}
+
+// 导出完课模板
+export function exportCourseFinishTempParent(query) {
+  return request({
+    url: '/course/courseFinishTempParent/export',
+    method: 'get',
+    params: query
+  })
+}

+ 39 - 0
src/components/Tip/index.vue

@@ -0,0 +1,39 @@
+<template>
+  <div v-if="show" class="title">
+    <p>{{ title }}</p>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'Tip',
+  props: {
+    title: {
+      type: String,
+      default: ''
+    },
+    show: {
+      type: Boolean,
+      default: true
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.title {
+  color: #E6A23C;
+  background: rgb(253, 246, 236);
+  border-radius: 2px;
+  padding: 4px 8px;
+  width: 100%;
+
+  p {
+    margin: 0;
+    white-space: pre-line;
+    font-size: 12px;
+    line-height: 24px;
+  }
+}
+
+</style>

+ 13 - 0
src/router/index.js

@@ -175,6 +175,19 @@ export const constantRoutes = [
       }
     ]
   },
+  {
+    path: '/qw/conversion',
+    component: Layout,
+    hidden: true,
+    children: [
+      {
+        path: 'courseFinishTemp/:parentId',
+        component: (resolve) => require(['@/views/course/courseFinishTemp/index'], resolve),
+        name: 'courseFinishTemp',
+        meta: { title: '模板详情', activeMenu: '/qw/conversion'}
+      }
+    ]
+  },
   {
     path: '/qw/sop',
     component: Layout,

+ 372 - 254
src/views/course/courseFinishTemp/index.vue

@@ -53,7 +53,8 @@
           size="mini"
           @click="handleAdd"
           v-hasPermi="['courseFinishTemp:course:add']"
-        >新增</el-button>
+        >新增
+        </el-button>
       </el-col>
       <el-col :span="1.5">
         <el-button
@@ -64,7 +65,8 @@
           :disabled="single"
           @click="handleUpdate"
           v-hasPermi="['courseFinishTemp:course:edit']"
-        >修改</el-button>
+        >修改
+        </el-button>
       </el-col>
       <el-col :span="1.5">
         <el-button
@@ -75,7 +77,8 @@
           :disabled="multiple"
           @click="handleDelete"
           v-hasPermi="['courseFinishTemp:course:remove']"
-        >删除</el-button>
+        >删除
+        </el-button>
       </el-col>
       <el-col :span="1.5">
         <el-button
@@ -86,24 +89,30 @@
           :loading="exportLoading"
           @click="handleExport"
           v-hasPermi="['courseFinishTemp:course:export']"
-        >导出</el-button>
+        >导出
+        </el-button>
       </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
 
     <el-table border v-loading="loading" :data="courseFinishTempList" @selection-change="handleSelectionChange">
-      <el-table-column type="selection" width="55" align="center" />
-      <el-table-column label="模板ID" align="center" prop="id" />
-      <el-table-column label="模板名称" align="center" prop="name" />
+      <el-table-column type="selection" width="55" align="center"/>
+      <el-table-column label="模板ID" align="center" prop="id"/>
+      <el-table-column label="模板名称" align="center" prop="name"/>
       <el-table-column label="状态" align="center" prop="status">
         <template slot-scope="scope">
           <dict-tag :options="statusOptions" :value="scope.row.status"/>
         </template>
       </el-table-column>
-      <el-table-column label="课程名称" align="center" prop="courseName" />
-      <el-table-column label="小节名称" align="center" prop="videoName" />
-      <el-table-column label="创建时间" align="center" prop="createTime" />
-      <el-table-column label="修改时间" align="center" prop="updateTime" />
+      <el-table-column label="课程名称" align="center" prop="courseName"/>
+      <el-table-column label="小节名称" align="center" prop="videoName"/>
+      <el-table-column label="创建时间" align="center" prop="createTime"/>
+      <el-table-column label="修改时间" align="center" prop="updateTime"/>
+      <el-table-column label="全选销售" align="center" prop="isAllCompanyUser">
+        <template slot-scope="scope">
+          <dict-tag :options="allowSelect" :value="scope.row.isAllCompanyUser"/>
+        </template>
+      </el-table-column>
       <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
         <template slot-scope="scope">
           <el-button
@@ -112,21 +121,24 @@
             icon="el-icon-edit"
             @click="handleUpdate(scope.row)"
             v-hasPermi="['courseFinishTemp:course:edit']"
-          >修改</el-button>
+          >修改
+          </el-button>
           <el-button
             size="mini"
             type="text"
             icon="el-icon-s-promotion"
             @click="handleSelectDetails(scope.row)"
             v-hasPermi="['courseFinishTemp:course:query']"
-          >详情</el-button>
+          >详情
+          </el-button>
           <el-button
             size="mini"
             type="text"
             icon="el-icon-delete"
             @click="handleDelete(scope.row)"
             v-hasPermi="['courseFinishTemp:course:remove']"
-          >删除</el-button>
+          >删除
+          </el-button>
         </template>
       </el-table-column>
     </el-table>
@@ -143,7 +155,7 @@
     <el-dialog :title="title" :visible.sync="open" width="1000px" append-to-body>
       <el-form ref="form" :model="form" :rules="rules" label-width="80px">
         <el-form-item label="模板名称" prop="name">
-          <el-input v-model="form.name" placeholder="请输入模板名称" />
+          <el-input v-model="form.name" placeholder="请输入模板名称"/>
         </el-form-item>
         <el-form-item label="状态">
           <el-radio-group v-model="form.status">
@@ -151,11 +163,13 @@
               v-for="dict in statusOptions"
               :key="dict.dictValue"
               :label="parseInt(dict.dictValue)"
-            >{{dict.dictLabel}}</el-radio>
+            >{{ dict.dictLabel }}
+            </el-radio>
           </el-radio-group>
         </el-form-item>
         <el-form-item label="选择课程">
-          <el-select  v-model="form.courseId" placeholder="请选择课程" style=" margin-right: 10px;" size="mini"  @change="courseChange()">
+          <el-select v-model="form.courseId" placeholder="请选择课程" style=" margin-right: 10px;" size="mini"
+                     @change="courseChange()">
             <el-option
               v-for="dict in courseList"
               :key="dict.dictValue"
@@ -163,7 +177,7 @@
               :value="parseInt(dict.dictValue)"
             />
           </el-select>
-          <el-select  v-model="form.videoId" placeholder="请选择小节" size="mini" style=" margin-right: 10px;" >
+          <el-select v-model="form.videoId" placeholder="请选择小节" size="mini" style=" margin-right: 10px;">
             <el-option
               v-for="dict in videoList"
               :key="dict.dictValue"
@@ -172,100 +186,219 @@
             />
           </el-select>
         </el-form-item>
-        <el-form-item label="规则" prop="setting"  >
-          <div v-for="(item, index) in setting" :key="index" style="background-color: #fdfdfd; border: 1px solid #e6e6e6; margin-bottom: 20px;">
-          <el-row>
-            <el-col :span="22">
-              <el-form :model="item" label-width="70px">
-                <el-form-item label="内容类别" style="margin: 2%">
-                    <el-radio-group  v-model="item.contentType">
-                      <el-radio   :label="item.dictValue" v-for="item in sysQwSopAiContentType">{{item.dictLabel}}</el-radio>
+        <el-form-item label="规则" prop="setting">
+          <div v-for="(item, index) in setting" :key="index"
+               style="background-color: #fdfdfd; border: 1px solid #e6e6e6; margin-bottom: 20px;">
+            <el-row>
+              <el-col :span="22">
+                <el-form :model="item" label-width="70px">
+                  <el-form-item label="内容类别" style="margin: 2%">
+                    <el-radio-group v-model="item.contentType">
+                      <el-radio :label="item.dictValue" v-for="item in sysQwSopAiContentType">{{ item.dictLabel }}
+                      </el-radio>
                     </el-radio-group>
-                </el-form-item>
-                <el-form-item label="内容" style="margin-bottom: 2%" >
-                  <el-input v-if="item.contentType == 1 " v-model="item.value" type="textarea" :rows="3" placeholder="内容" style="width: 90%;margin-top: 10px;"/>
-
-                  <ImageUpload v-if="item.contentType == 2 " v-model="item.imgUrl" type="image" :num="1"  :width="150" :height="150" />
-
-                  <div v-if="item.contentType == 3 ">
-                    <el-card class="box-card">
-                      <el-form-item label="链接标题:"  label-width="100px">
-                        <el-input v-model="item.linkTitle" placeholder="请输入链接标题" style="width: 90%;"/>
+                  </el-form-item>
+                  <el-form-item label="内容" style="margin-bottom: 2%">
+                    <el-input v-if="item.contentType == 1 " v-model="item.value" type="textarea" :rows="3"
+                              placeholder="内容" style="width: 90%;margin-top: 10px;"/>
+
+                    <ImageUpload v-if="item.contentType == 2 " v-model="item.imgUrl" type="image" :num="1" :width="150"
+                                 :height="150"/>
+
+                    <div v-if="item.contentType == 3 ">
+                      <el-card class="box-card">
+                        <el-form-item label="链接标题:" label-width="100px">
+                          <el-input v-model="item.linkTitle" placeholder="请输入链接标题" style="width: 90%;"/>
+                        </el-form-item>
+                        <el-form-item label="链接描述:" label-width="100px">
+                          <el-input type="textarea" :rows="3" v-model="item.linkDescribe" placeholder="请输入链接描述"
+                                    style="width: 90%;margin-top: 1%;"/>
+                        </el-form-item>
+                        <el-form-item label="链接封面:" label-width="100px">
+                          <ImageUpload v-model="item.linkImageUrl" type="image" :num="1" :file-size="2" :width="150"
+                                       :height="150" style="margin-top: 1%;"/>
+                        </el-form-item>
+                        <el-form-item label="链接地址:" label-width="100px">
+                          <el-input v-model="item.linkUrl" placeholder="请输入链接地址" style="width: 90%;"/>
+                        </el-form-item>
+                      </el-card>
+                    </div>
+                    <div v-if="item.contentType == 4">
+
+                    </div>
+                    <div v-if="item.contentType == 5 ">
+
+                      <el-form-item label="上传文件:" prop="fileUrl" label-width="100px">
+                        <el-upload
+                          v-model="item.fileUrl"
+                          class="avatar-uploader"
+                          :action="uploadUrl"
+                          :show-file-list="false"
+                          :on-success="(res, file) => handleAvatarSuccessFile(res, file, item)"
+                          :before-upload="beforeAvatarUploadFile">
+                          <i class="el-icon-plus avatar-uploader-icon"></i>
+                        </el-upload>
+                        <el-link v-if="item.fileUrl" type="primary" :href="downloadUrl(item.fileUrl)" download>
+                          {{ item.fileUrl }}
+                        </el-link>
                       </el-form-item>
-                      <el-form-item label="链接描述:"   label-width="100px" >
-                        <el-input type="textarea" :rows="3" v-model="item.linkDescribe" placeholder="请输入链接描述" style="width: 90%;margin-top: 1%;"/>
+
+                    </div>
+
+                    <div v-if="item.contentType == 6 ">
+                      <el-form-item label="上传视频:" prop="videoUrl" label-width="100px">
+                        <el-upload
+                          v-model="item.videoUrl"
+                          class="avatar-uploader"
+                          :action="uploadUrl"
+                          :show-file-list="false"
+                          :on-success="(res, file) => handleAvatarSuccessVideo(res, file, item)"
+                          :before-upload="beforeAvatarUploadVideo">
+                          <i class="el-icon-plus avatar-uploader-icon"></i>
+                        </el-upload>
+                        <video v-if="item.videoUrl"
+                               :src="item.videoUrl"
+                               controls style="width: 200px;height: 100px">
+                        </video>
                       </el-form-item>
-                      <el-form-item label="链接封面:"   label-width="100px">
-                        <ImageUpload v-model="item.linkImageUrl" type="image" :num="1" :file-size="2" :width="150" :height="150" style="margin-top: 1%;" />
+                    </div>
+                    <div v-if="item.contentType == 7 ">
+                      <el-input
+                        v-model="item.value"
+                        type="textarea" :rows="3" maxlength="66" show-word-limit
+                        placeholder="输入要转为语音的内容" style="width: 90%;margin-top: 10px;"
+                        @input="handleInputVideoText(item.value,item)"/>
+                    </div>
+                    <div v-if="item.contentType == 8">
+
+                    </div>
+
+                  </el-form-item>
+                </el-form>
+              </el-col>
+              <el-col :span="1" :offset="1">
+                <i class="el-icon-delete" @click="delSetList(index, 0)" style="margin-top: 20px;"
+                   v-if="setting.length>1 && formType==1"></i>
+              </el-col>
+            </el-row>
+          </div>
+          <el-link type="primary" class="el-icon-plus" :underline="false" @click='addSetList(0)' v-if="formType==1">
+            添加内容
+          </el-link>
+        </el-form-item>
+        <el-form-item label="群聊恭喜规则" prop="setting">
+          <div v-for="(item, index) in chatSetting" :key="index"
+               style="background-color: #fdfdfd; border: 1px solid #e6e6e6; margin-bottom: 20px;">
+            <el-row>
+              <el-col :span="22">
+                <el-form :model="item" label-width="70px">
+                  <el-form-item label="内容类别" style="margin: 2%">
+                    <el-radio-group v-model="item.contentType">
+                      <el-radio :label="item.dictValue" v-for="item in sysQwSopAiContentType">{{ item.dictLabel }}
+                      </el-radio>
+                    </el-radio-group>
+                  </el-form-item>
+                  <el-form-item label="内容" style="margin-bottom: 2%">
+                    <el-input v-if="item.contentType == 1 " v-model="item.value" type="textarea" :rows="3"
+                              placeholder="内容" style="width: 90%;margin-top: 10px;"/>
+
+                    <ImageUpload v-if="item.contentType == 2 " v-model="item.imgUrl" type="image" :num="1" :width="150"
+                                 :height="150"/>
+
+                    <div v-if="item.contentType == 3 ">
+                      <el-card class="box-card">
+                        <el-form-item label="链接标题:" label-width="100px">
+                          <el-input v-model="item.linkTitle" placeholder="请输入链接标题" style="width: 90%;"/>
+                        </el-form-item>
+                        <el-form-item label="链接描述:" label-width="100px">
+                          <el-input type="textarea" :rows="3" v-model="item.linkDescribe" placeholder="请输入链接描述"
+                                    style="width: 90%;margin-top: 1%;"/>
+                        </el-form-item>
+                        <el-form-item label="链接封面:" label-width="100px">
+                          <ImageUpload v-model="item.linkImageUrl" type="image" :num="1" :file-size="2" :width="150"
+                                       :height="150" style="margin-top: 1%;"/>
+                        </el-form-item>
+                        <el-form-item label="链接地址:" label-width="100px">
+                          <el-input v-model="item.linkUrl" placeholder="请输入链接地址" style="width: 90%;"/>
+                        </el-form-item>
+                      </el-card>
+                    </div>
+                    <div v-if="item.contentType == 4">
+
+                    </div>
+                    <div v-if="item.contentType == 5 ">
+
+                      <el-form-item label="上传文件:" prop="fileUrl" label-width="100px">
+                        <el-upload
+                          v-model="item.fileUrl"
+                          class="avatar-uploader"
+                          :action="uploadUrl"
+                          :show-file-list="false"
+                          :on-success="(res, file) => handleAvatarSuccessFile(res, file, item)"
+                          :before-upload="beforeAvatarUploadFile">
+                          <i class="el-icon-plus avatar-uploader-icon"></i>
+                        </el-upload>
+                        <el-link v-if="item.fileUrl" type="primary" :href="downloadUrl(item.fileUrl)" download>
+                          {{ item.fileUrl }}
+                        </el-link>
                       </el-form-item>
-                      <el-form-item label="链接地址:"  label-width="100px" >
-                        <el-input v-model="item.linkUrl" placeholder="请输入链接地址" style="width: 90%;"/>
+
+                    </div>
+
+                    <div v-if="item.contentType == 6 ">
+                      <el-form-item label="上传视频:" prop="videoUrl" label-width="100px">
+                        <el-upload
+                          v-model="item.videoUrl"
+                          class="avatar-uploader"
+                          :action="uploadUrl"
+                          :show-file-list="false"
+                          :on-success="(res, file) => handleAvatarSuccessVideo(res, file, item)"
+                          :before-upload="beforeAvatarUploadVideo">
+                          <i class="el-icon-plus avatar-uploader-icon"></i>
+                        </el-upload>
+                        <video v-if="item.videoUrl"
+                               :src="item.videoUrl"
+                               controls style="width: 200px;height: 100px">
+                        </video>
                       </el-form-item>
-                    </el-card>
-                  </div>
-                  <div v-if="item.contentType == 4">
-
-                  </div>
-                  <div v-if="item.contentType == 5 ">
-
-                    <el-form-item label="上传文件:" prop="fileUrl" label-width="100px">
-                      <el-upload
-                        v-model="item.fileUrl"
-                        class="avatar-uploader"
-                        :action="uploadUrl"
-                        :show-file-list="false"
-                        :on-success="(res, file) => handleAvatarSuccessFile(res, file, item)"
-                        :before-upload="beforeAvatarUploadFile">
-                        <i class="el-icon-plus avatar-uploader-icon"></i>
-                      </el-upload>
-                      <el-link v-if="item.fileUrl" type="primary" :href="downloadUrl(item.fileUrl)" download>
-                        {{item.fileUrl}}
-                      </el-link>
-                    </el-form-item>
-
-                  </div>
-
-                  <div v-if="item.contentType == 6 ">
-                    <el-form-item label="上传视频:" prop="videoUrl" label-width="100px">
-                      <el-upload
-                        v-model="item.videoUrl"
-                        class="avatar-uploader"
-                        :action="uploadUrl"
-                        :show-file-list="false"
-                        :on-success="(res, file) => handleAvatarSuccessVideo(res, file, item)"
-                        :before-upload="beforeAvatarUploadVideo">
-                        <i class="el-icon-plus avatar-uploader-icon"></i>
-                      </el-upload>
-                      <video v-if="item.videoUrl"
-                             :src="item.videoUrl"
-                             controls style="width: 200px;height: 100px">
-                      </video>
-                    </el-form-item>
-                  </div>
-                  <div v-if="item.contentType == 7 ">
+                    </div>
+                    <div v-if="item.contentType == 7 ">
                       <el-input
                         v-model="item.value"
                         type="textarea" :rows="3" maxlength="66" show-word-limit
                         placeholder="输入要转为语音的内容" style="width: 90%;margin-top: 10px;"
                         @input="handleInputVideoText(item.value,item)"/>
-                  </div>
-                  <div v-if="item.contentType == 8">
-
-                  </div>
-
-                </el-form-item>
-              </el-form>
-            </el-col>
-            <el-col :span="1" :offset="1">
-              <i class="el-icon-delete" @click="delSetList(index)" style="margin-top: 20px;" v-if="setting.length>1 && formType==1"></i>
-            </el-col>
-          </el-row>
+                    </div>
+                    <div v-if="item.contentType == 8">
+
+                    </div>
+
+                  </el-form-item>
+                </el-form>
+              </el-col>
+              <el-col :span="1" :offset="1">
+                <i class="el-icon-delete" @click="delSetList(index,1)" style="margin-top: 20px;"
+                   v-if="setting.length>1 && formType==1"></i>
+              </el-col>
+            </el-row>
           </div>
-        <el-link type="primary" class="el-icon-plus" :underline="false" @click='addSetList()' v-if="formType==1" >添加内容</el-link>
-
+          <el-link type="primary" class="el-icon-plus" :underline="false" @click='addSetList(1)' v-if="formType==1">
+            添加内容
+          </el-link>
+        </el-form-item>
+        <el-form-item label="全选销售" prop="isAllCompanyUser">
+          <el-switch
+            v-model="form.isAllCompanyUser"
+            active-color="#13ce66"
+            inactive-color="#ff4949"
+            :active-value="1"
+            :inactive-value="2">
+          </el-switch>
+          <span v-if="form.isAllCompanyUser == '1'" style="margin-left: 10px;color: #13ce66">是</span>
+          <span v-else style="margin-left: 10px;color: #ff4949">否</span>
         </el-form-item>
         <el-form-item label="所属销售" prop="companyUserIds">
-          <el-select v-model="companyUserIds" remote multiple placeholder="请选择" filterable  style="width: 100%;">
+          <el-select v-model="companyUserIds" remote multiple placeholder="请选择" filterable style="width: 100%;">
             <el-option
               v-for="dict in userList"
               :key="dict.userId"
@@ -284,10 +417,17 @@
 </template>
 
 <script>
-import { listCourseFinishTemp, getCourseFinishTemp, addCourseFinishTemp, updateCourseFinishTemp, delCourseFinishTemp, exportCourseFinishTemp } from "@/api/course/courseFinishTemp";
+import {
+  addCourseFinishTemp,
+  delCourseFinishTemp,
+  exportCourseFinishTemp,
+  getCourseFinishTemp,
+  listCourseFinishTemp,
+  updateCourseFinishTemp
+} from '@/api/course/courseFinishTemp'
 import { getUserList } from '@/api/company/companyUser'
-import {courseList, videoList} from '@/api/qw/sop'
-import ImageUpload from "@/views/qw/sop/ImageUpload.vue";
+import { courseList, videoList } from '@/api/qw/sop'
+import ImageUpload from '@/views/qw/sop/ImageUpload.vue'
 
 export default {
   name: "CourseFinishTemp",
@@ -295,15 +435,16 @@ export default {
   data() {
     return {
       //上传语音的遮罩层
-      voiceLoading :false,
-      uploadUrl:process.env.VUE_APP_BASE_API+"/common/uploadOSS2",
-      uploadUrlByVoice:process.env.VUE_APP_BASE_API+"/common/uploadOSSByHOOKVoice",
-      companyUserIds:[],
-      userList:[],
+      voiceLoading: false,
+      uploadUrl: process.env.VUE_APP_BASE_API + "/common/uploadOSS2",
+      uploadUrlByVoice: process.env.VUE_APP_BASE_API + "/common/uploadOSSByHOOKVoice",
+      companyUserIds: [],
+      userList: [],
       // 状态字典
       statusOptions: [],
-      courseList:[],
-      videoList:[],
+      allowSelect: [],
+      courseList: [],
+      videoList: [],
       // 遮罩层
       loading: true,
       // 导出遮罩层
@@ -316,13 +457,13 @@ export default {
       multiple: true,
       // 显示搜索条件
       showSearch: true,
-      formType:1,
+      formType: 1,
       // 总条数
       total: 0,
       // 完课模板表格数据
       courseFinishTempList: [],
       //插件版
-      sysQwSopAiContentType:[],
+      sysQwSopAiContentType: [],
 
       sysFsSopWatchStatus: [],
 
@@ -337,6 +478,7 @@ export default {
         name: null,
         status: null,
         setting: null,
+        chatSetting: null,
         companyId: null,
         courseId: null,
         videoId: null,
@@ -345,43 +487,50 @@ export default {
       },
       // 模板表格数据
       setting: [],
+      chatSetting: [],
       // 表单参数
       form: {
-        setting:null,
-        videoIdSet:null,
-        courseIdSet:null,
+        setting: null,
+        chatSetting: null,
+        videoIdSet: null,
+        courseIdSet: null,
       },
       // 表单校验
-      rules: {
-      }
+      rules: {}
     };
   },
   created() {
-    this.getList();
+    this.queryParams.parentId = this.$route.params && this.$route.params.parentId;
     getUserList().then(response => {
-      this.userList =  response.data;
-      console.log("this.userList",this.userList)
+      this.userList = response.data;
+      console.log("this.userList", this.userList)
     });
     this.getDicts("sys_company_status").then(response => {
       this.statusOptions = response.data;
     });
 
+    //复用一下
+    this.getDicts("sys_qw_allow_select").then(response => {
+      this.allowSelect = response.data;
+    });
+
     this.getDicts("sys_fs_sop_watch_status").then(response => {
       this.sysFsSopWatchStatus = response.data;
     });
 
-    this.getDicts("sys_qwSopCourse_contentType").then(response => {
+    this.getDicts("sys_qwSopAi_contentType").then(response => {
       this.sysQwSopAiContentType = response.data;
     });
     courseList().then(response => {
       this.courseList = response.list;
     });
+    this.getList();
   },
   methods: {
     courseChange() {
 
       videoList(this.form.courseId).then(response => {
-        this.videoList=response.list;
+        this.videoList = response.list;
       });
     },
     /** 查询完课模板列表 */
@@ -407,7 +556,7 @@ export default {
       }
     },
 
-    beforeAvatarUploadFile(file){
+    beforeAvatarUploadFile(file) {
       const isLt1M = file.size / 1024 / 1024 < 10;
       if (!isLt1M) {
         this.$message.error('上传大小不能超过 10MB!');
@@ -419,7 +568,7 @@ export default {
       // 直接返回文件 URL
       return materialUrl;
     },
-    handleInputVideoText(value,content){
+    handleInputVideoText(value, content) {
       // 允许的字符:中文、英文(大小写)、数字和指定标点符号(,。!?)
       const regex = /^[\u4e00-\u9fa5,。!?,!?]+$/;
 
@@ -430,16 +579,15 @@ export default {
 
     },
     handleAvatarSuccessVideo(res, file, item) {
-      if(res.code==200){
+      if (res.code == 200) {
         // 使用 $set 确保响应式更新
         this.$set(item, 'videoUrl', res.url);
-      }
-      else{
+      } else {
         this.msgError(res.msg);
       }
     },
 
-    beforeAvatarUploadVideo(file){
+    beforeAvatarUploadVideo(file) {
       const isLt30M = file.size / 1024 / 1024 < 10;
       const isMP4 = file.type === 'video/mp4';
 
@@ -456,82 +604,34 @@ export default {
       return true;
     },
 
-    handleAvatarSuccessVoice(res, file, item){
-      if(res.code==200){
-
-        // 创建 Audio 对象加载音频
-        const audio = new Audio(res.mp3Url);
-        audio.addEventListener('loadedmetadata', () => {
-          // 获取音频时长
-          this.$set(item, 'voiceDuration', Math.ceil(audio.duration));
-        });
-        // 使用 $set 确保响应式更新
-        this.$set(item, 'voiceUrl', res.silkUrl);
-        this.$set(item, 'mp3Url', res.mp3Url);
-      }
-      else{
-        this.msgError(res.msg);
+    delSetList(index, type) {
+      if (type == 0) {
+        this.setting.splice(index, 1)
+      } else {
+        this.chatSetting.splice(index, 1)
       }
-      this.voiceLoading=false;
-    },
-    beforeAvatarUploadVoice(file) {
-      return new Promise((resolve, reject) => {
-        const isLt10M = file.size / 1024 / 1024 < 10; // 假设语音文件大小限制为10MB
-        const isVoiceType = ['audio/mp3', 'audio/mpeg', 'audio/wav', 'audio/x-wav'].includes(file.type);
-
-        if (!isVoiceType) {
-          this.$message.error('仅支持上传 MP3, WAV, X-WAV 格式的语音文件!');
-          return reject(false); // 不允许继续上传
-        }
-
-        if (!isLt10M) {
-          this.$message.error('上传大小不能超过 10MB!');
-          return reject(false); // 不允许继续上传
-        }
-
-        // 使用 FileReader 读取文件
-        const reader = new FileReader();
-        reader.onload = (event) => {
-          const audio = new Audio(event.target.result);
-          audio.addEventListener('loadedmetadata', () => {
-            // 获取时长并保存
-            if (Math.ceil(audio.duration) > 30) {
-              this.$message.error('音频时长不能超过30秒!');
-              this.voiceLoading=false;
-              return reject(false); // 不允许继续上传
-            }
-            resolve(true); // 允许上传
-          });
-        };
-
-        reader.onerror = () => {
-          this.$message.error('无法读取音频文件!请上传正确的音频文件');
-          reject(false); // 不允许继续上传
-        };
-        this.voiceLoading=true;
-        reader.readAsDataURL(file); // 开始读取文件
-      });
     },
-    delSetList(index){
-      this.setting.splice(index,1)
-    },
-
-    addSetList(){
-        const newSetting = {
-          contentType:'1',
-          value: '',
-        };
-        // 将新设置项添加到 content.setting 数组中
+    addSetList(type) {
+      const newSetting = {
+        contentType: '1',
+        value: '',
+      };
+      // 将新设置项添加到 content.setting 数组中
+      if (type == 0) {
         this.setting.push(newSetting);
-
+      } else {
+        this.chatSetting.push(newSetting);
+      }
     },
     // 表单重置
     reset() {
       this.form = {
         id: null,
         name: null,
+        type: 1,
         status: 1,
         setting: [],
+        chatSetting: [],
         companyId: null,
         createBy: null,
         createTime: null,
@@ -539,10 +639,12 @@ export default {
         videoId: null,
         companyUserIds: null,
         updateTime: null,
-        isDel: null
+        isDel: null,
+        isAllCompanyUser: null,
       };
-      this.companyUserIds=[]
-      this.setting=[]
+      this.companyUserIds = []
+      this.setting = []
+      this.chatSetting = []
       this.resetForm("form");
     },
     /** 搜索按钮操作 */
@@ -558,7 +660,7 @@ export default {
     // 多选框选中数据
     handleSelectionChange(selection) {
       this.ids = selection.map(item => item.id)
-      this.single = selection.length!==1
+      this.single = selection.length !== 1
       this.multiple = !selection.length
     },
     /** 新增按钮操作 */
@@ -569,26 +671,29 @@ export default {
     },
 
     /**
-    * 查看完课模板
-    */
-    handleSelectDetails(row){
+     * 查看完课模板
+     */
+    handleSelectDetails(row) {
 
       this.reset();
       const id = row.id || this.ids
       getCourseFinishTemp(id).then(response => {
+        console.log("this.form222 ", response.data)
         this.form = response.data;
-        this.setting=JSON.parse(this.form.setting)
-        if (response.data.companyUserIds!=null){
+
+        this.setting = JSON.parse(this.form.setting)
+        this.chatSetting = JSON.parse(this.form.chatSetting)
+        if (response.data.companyUserIds != null) {
           this.companyUserIds = this.form.companyUserIds.split(",");
         }
 
         videoList(this.form.courseId).then(response => {
-          this.videoList=response.list;
+          this.videoList = response.list;
         });
 
         this.open = true;
         this.title = "查看完课模板";
-        this.formType=2;
+        this.formType = 2;
 
       });
     },
@@ -597,16 +702,20 @@ export default {
       this.reset();
       const id = row.id || this.ids
       getCourseFinishTemp(id).then(response => {
+        console.log("this.response.data", response.data)
         this.form = response.data;
-        this.setting=JSON.parse(this.form.setting)
-        if (response.data.companyUserIds!=null){
+
+        this.setting = JSON.parse(this.form.setting)
+        this.chatSetting = JSON.parse(this.form.chatSetting)
+        if (response.data.companyUserIds != null) {
           this.companyUserIds = this.form.companyUserIds.split(",");
         }
 
         videoList(this.form.courseId).then(response => {
-          this.videoList=response.list;
+          this.videoList = response.list;
         });
 
+
         this.open = true;
         this.title = "修改完课模板";
 
@@ -616,40 +725,45 @@ export default {
     submitForm() {
       this.$refs["form"].validate(valid => {
         if (valid) {
+
+          if (this.form.isAllCompanyUser == null) {
+            this.form.isAllCompanyUser = 2;
+          }
           this.form.companyUserIds = this.companyUserIds.toString()
 
-          this.form.setting=JSON.stringify(this.setting)
+          this.form.setting = JSON.stringify(this.setting)
+          this.form.chatSetting = JSON.stringify(this.chatSetting)
 
           if (this.setting.length <= 0) {
             return this.$message("请添加规则")
           }
           for (let i = 0; i < this.setting.length; i++) {
-                  if (this.setting[i].contentType == 1 && (this.setting[i].value == null || this.setting[i].value == "")) {
-                    return this.$message.error("内容不能为空")
-                  }
-                  if (this.setting[i].contentType == 2 && (this.setting[i].imgUrl == null || this.setting[i].imgUrl == "")) {
-                    return this.$message.error("图片不能为空")
-                  }
-                  if (this.setting[i].contentType == 3 && (this.setting[i].linkTitle == null || this.setting[i].linkTitle == "")) {
-                    return this.$message.error("链接标题不能为空")
-                  }
-                  if (this.setting[i].contentType == 3 && (this.setting[i].linkDescribe == null || this.setting[i].linkDescribe == "")) {
-                    return this.$message.error("链接描述不能为空")
-                  }
-                  if (this.setting[i].contentType == 3 && (this.setting[i].linkImageUrl == null || this.setting[i].linkImageUrl == "")) {
-                    return this.$message.error("链接图片不能为空")
-                  }
-                  if (this.setting[i].contentType == 3 && this.setting[i].type == 1 && (this.setting[i].linkUrl == null || this.setting[i].linkUrl == "")) {
-                    return this.$message.error("链接地址不能为空")
-                  }
-                  if (this.setting[i].contentType == 5 && (this.setting[i].fileUrl == null || this.setting[i].fileUrl == "")) {
-                    return this.$message.error("文件不能为空")
-                  }
-                  if (this.setting[i].contentType == 6 && (this.setting[i].videoUrl == null || this.setting[i].videoUrl == "")) {
-                    return this.$message.error("视频不能为空")
-                  }
-                  if (this.setting[i].contentType == 7 && (this.setting[i].value == null || this.setting[i].value == "")) {
-                    return this.$message.error("语音不能为空")
+            if (this.setting[i].contentType == 1 && (this.setting[i].value == null || this.setting[i].value == "")) {
+              return this.$message.error("内容不能为空")
+            }
+            if (this.setting[i].contentType == 2 && (this.setting[i].imgUrl == null || this.setting[i].imgUrl == "")) {
+              return this.$message.error("图片不能为空")
+            }
+            if (this.setting[i].contentType == 3 && (this.setting[i].linkTitle == null || this.setting[i].linkTitle == "")) {
+              return this.$message.error("链接标题不能为空")
+            }
+            if (this.setting[i].contentType == 3 && (this.setting[i].linkDescribe == null || this.setting[i].linkDescribe == "")) {
+              return this.$message.error("链接描述不能为空")
+            }
+            if (this.setting[i].contentType == 3 && (this.setting[i].linkImageUrl == null || this.setting[i].linkImageUrl == "")) {
+              return this.$message.error("链接图片不能为空")
+            }
+            if (this.setting[i].contentType == 3 && this.setting[i].type == 1 && (this.setting[i].linkUrl == null || this.setting[i].linkUrl == "")) {
+              return this.$message.error("链接地址不能为空")
+            }
+            if (this.setting[i].contentType == 5 && (this.setting[i].fileUrl == null || this.setting[i].fileUrl == "")) {
+              return this.$message.error("文件不能为空")
+            }
+            if (this.setting[i].contentType == 6 && (this.setting[i].videoUrl == null || this.setting[i].videoUrl == "")) {
+              return this.$message.error("视频不能为空")
+            }
+            if (this.setting[i].contentType == 7 && (this.setting[i].value == null || this.setting[i].value == "")) {
+              return this.$message.error("语音不能为空")
             }
           }
 
@@ -658,13 +772,15 @@ export default {
               this.msgSuccess("修改成功");
               this.open = false;
               this.getList();
-              this.setting=[];
+              this.setting = [];
+              this.chatSetting = [];
             });
           } else {
             addCourseFinishTemp(this.form).then(response => {
               this.msgSuccess("新增成功");
               this.open = false;
-              this.setting=[];
+              this.setting = [];
+              this.chatSetting = [];
               this.getList();
             });
           }
@@ -675,30 +791,32 @@ export default {
     handleDelete(row) {
       const ids = row.id || this.ids;
       this.$confirm('是否确认删除完课模板编号为"' + ids + '"的数据项?', "警告", {
-          confirmButtonText: "确定",
-          cancelButtonText: "取消",
-          type: "warning"
-        }).then(function() {
-          return delCourseFinishTemp(ids);
-        }).then(() => {
-          this.getList();
-          this.msgSuccess("删除成功");
-        }).catch(() => {});
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(function () {
+        return delCourseFinishTemp(ids);
+      }).then(() => {
+        this.getList();
+        this.msgSuccess("删除成功");
+      }).catch(() => {
+      });
     },
     /** 导出按钮操作 */
     handleExport() {
       const queryParams = this.queryParams;
       this.$confirm('是否确认导出所有完课模板数据项?', "警告", {
-          confirmButtonText: "确定",
-          cancelButtonText: "取消",
-          type: "warning"
-        }).then(() => {
-          this.exportLoading = true;
-          return exportCourseFinishTemp(queryParams);
-        }).then(response => {
-          this.download(response.msg);
-          this.exportLoading = false;
-        }).catch(() => {});
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        this.exportLoading = true;
+        return exportCourseFinishTemp(queryParams);
+      }).then(response => {
+        this.download(response.msg);
+        this.exportLoading = false;
+      }).catch(() => {
+      });
     }
   }
 };

+ 699 - 0
src/views/course/courseFinishTempParent/index.vue

@@ -0,0 +1,699 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="名称" prop="name">
+        <el-input
+          v-model="queryParams.name"
+          placeholder="请输入名称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="课程" prop="courseId">
+        <el-select v-model="queryParams.courseId" clearable placeholder="请选择课程" style=" margin-right: 10px;" size="mini">
+          <el-option
+            v-for="dict in courseList"
+            :key="dict.dictValue"
+            :label="dict.dictLabel"
+            :value="parseInt(dict.dictValue)"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['course:courseFinishTempParent:add']"
+        >新增</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          plain
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['course:courseFinishTempParent:edit']"
+        >修改</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['course:courseFinishTempParent:remove']"
+        >删除</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          :loading="exportLoading"
+          @click="handleExport"
+          v-hasPermi="['course:courseFinishTempParent:export']"
+        >导出</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table border v-loading="loading" :data="courseFinishTempParentList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="名称" align="center" prop="name" />
+      <el-table-column label="课程" align="center" prop="courseId">
+        <template slot-scope="scope">
+          <el-tag v-for="dict in courseList" v-if="dict.dictValue == scope.row.courseId">{{dict.dictLabel}}</el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['course:courseFinishTempParent:edit']"
+          >修改</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            @click="jump(scope.row.id)"
+          >模板列表</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['course:courseFinishTempParent:remove']"
+          >删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 添加或修改完课模板对话框 -->
+    <el-dialog :title="title" :visible.sync="open" width="1000px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="名称" prop="name">
+          <el-input v-model="form.name" placeholder="请输入名称" />
+        </el-form-item>
+        <el-form-item label="状态" v-if="!form.id">
+          <el-radio-group v-model="form.status">
+            <el-radio
+              v-for="dict in statusOptions"
+              :key="dict.dictValue"
+              :label="parseInt(dict.dictValue)"
+            >{{ dict.dictLabel }}
+            </el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="课程ID" prop="courseId">
+          <el-select v-model="form.courseId" :disabled="form.id != null" placeholder="请选择课程" style=" margin-right: 10px;" size="mini">
+            <el-option
+              v-for="dict in courseList"
+              :key="dict.dictValue"
+              :label="dict.dictLabel"
+              :value="parseInt(dict.dictValue)"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="规则" prop="setting" v-if="!form.id">
+          <div v-for="(item, index) in setting" :key="index"
+               style="background-color: #fdfdfd; border: 1px solid #e6e6e6; margin-bottom: 20px;">
+            <el-row>
+              <el-col :span="22">
+                <el-form :model="item" label-width="70px">
+                  <el-form-item label="内容类别" style="margin: 2%">
+                    <el-radio-group v-model="item.contentType">
+                      <el-radio :label="item.dictValue" v-for="item in sysQwSopAiContentType">{{ item.dictLabel }}
+                      </el-radio>
+                    </el-radio-group>
+                  </el-form-item>
+                  <el-form-item label="内容" style="margin-bottom: 2%">
+                    <el-input v-if="item.contentType == 1 " v-model="item.value" type="textarea" :rows="3"
+                              placeholder="内容" style="width: 90%;margin-top: 10px;"/>
+
+                    <ImageUpload v-if="item.contentType == 2 " v-model="item.imgUrl" type="image" :num="1" :width="150"
+                                 :height="150"/>
+
+                    <div v-if="item.contentType == 3 ">
+                      <el-card class="box-card">
+                        <el-form-item label="链接标题:" label-width="100px">
+                          <el-input v-model="item.linkTitle" placeholder="请输入链接标题" style="width: 90%;"/>
+                        </el-form-item>
+                        <el-form-item label="链接描述:" label-width="100px">
+                          <el-input type="textarea" :rows="3" v-model="item.linkDescribe" placeholder="请输入链接描述"
+                                    style="width: 90%;margin-top: 1%;"/>
+                        </el-form-item>
+                        <el-form-item label="链接封面:" label-width="100px">
+                          <ImageUpload v-model="item.linkImageUrl" type="image" :num="1" :file-size="2" :width="150"
+                                       :height="150" style="margin-top: 1%;"/>
+                        </el-form-item>
+                        <el-form-item label="链接地址:" label-width="100px">
+                          <el-input v-model="item.linkUrl" placeholder="请输入链接地址" style="width: 90%;"/>
+                        </el-form-item>
+                      </el-card>
+                    </div>
+                    <div v-if="item.contentType == 4">
+
+                    </div>
+                    <div v-if="item.contentType == 5 ">
+
+                      <el-form-item label="上传文件:" prop="fileUrl" label-width="100px">
+                        <el-upload
+                          v-model="item.fileUrl"
+                          class="avatar-uploader"
+                          :action="uploadUrl"
+                          :show-file-list="false"
+                          :on-success="(res, file) => handleAvatarSuccessFile(res, file, item)"
+                          :before-upload="beforeAvatarUploadFile">
+                          <i class="el-icon-plus avatar-uploader-icon"></i>
+                        </el-upload>
+                        <el-link v-if="item.fileUrl" type="primary" :href="downloadUrl(item.fileUrl)" download>
+                          {{ item.fileUrl }}
+                        </el-link>
+                      </el-form-item>
+
+                    </div>
+
+                    <div v-if="item.contentType == 6 ">
+                      <el-form-item label="上传视频:" prop="videoUrl" label-width="100px">
+                        <el-upload
+                          v-model="item.videoUrl"
+                          class="avatar-uploader"
+                          :action="uploadUrl"
+                          :show-file-list="false"
+                          :on-success="(res, file) => handleAvatarSuccessVideo(res, file, item)"
+                          :before-upload="beforeAvatarUploadVideo">
+                          <i class="el-icon-plus avatar-uploader-icon"></i>
+                        </el-upload>
+                        <video v-if="item.videoUrl"
+                               :src="item.videoUrl"
+                               controls style="width: 200px;height: 100px">
+                        </video>
+                      </el-form-item>
+                    </div>
+                    <div v-if="item.contentType == 7 ">
+                      <el-input
+                        v-model="item.value"
+                        type="textarea" :rows="3" maxlength="66" show-word-limit
+                        placeholder="输入要转为语音的内容" style="width: 90%;margin-top: 10px;"
+                        @input="handleInputVideoText(item.value,item)"/>
+                    </div>
+                    <div v-if="item.contentType == 8">
+
+                    </div>
+
+                  </el-form-item>
+                </el-form>
+              </el-col>
+              <el-col :span="1" :offset="1">
+                <i class="el-icon-delete" @click="delSetList(index, 0)" style="margin-top: 20px;"
+                   v-if="setting.length>1"></i>
+              </el-col>
+            </el-row>
+          </div>
+          <el-link type="primary" class="el-icon-plus" :underline="false" @click='addSetList(0)'>
+            添加内容
+          </el-link>
+        </el-form-item>
+        <el-form-item label="群聊恭喜规则" prop="setting" v-if="!form.id">
+          <div v-for="(item, index) in chatSetting" :key="index"
+               style="background-color: #fdfdfd; border: 1px solid #e6e6e6; margin-bottom: 20px;">
+            <el-row>
+              <el-col :span="22">
+                <el-form :model="item" label-width="70px">
+                  <el-form-item label="内容类别" style="margin: 2%">
+                    <el-radio-group v-model="item.contentType">
+                      <el-radio :label="item.dictValue" v-for="item in sysQwSopAiContentType">{{ item.dictLabel }}
+                      </el-radio>
+                    </el-radio-group>
+                  </el-form-item>
+                  <el-form-item label="内容" style="margin-bottom: 2%">
+                    <el-input v-if="item.contentType == 1 " v-model="item.value" type="textarea" :rows="3"
+                              placeholder="内容" style="width: 90%;margin-top: 10px;"/>
+
+                    <ImageUpload v-if="item.contentType == 2 " v-model="item.imgUrl" type="image" :num="1" :width="150"
+                                 :height="150"/>
+
+                    <div v-if="item.contentType == 3 ">
+                      <el-card class="box-card">
+                        <el-form-item label="链接标题:" label-width="100px">
+                          <el-input v-model="item.linkTitle" placeholder="请输入链接标题" style="width: 90%;"/>
+                        </el-form-item>
+                        <el-form-item label="链接描述:" label-width="100px">
+                          <el-input type="textarea" :rows="3" v-model="item.linkDescribe" placeholder="请输入链接描述"
+                                    style="width: 90%;margin-top: 1%;"/>
+                        </el-form-item>
+                        <el-form-item label="链接封面:" label-width="100px">
+                          <ImageUpload v-model="item.linkImageUrl" type="image" :num="1" :file-size="2" :width="150"
+                                       :height="150" style="margin-top: 1%;"/>
+                        </el-form-item>
+                        <el-form-item label="链接地址:" label-width="100px">
+                          <el-input v-model="item.linkUrl" placeholder="请输入链接地址" style="width: 90%;"/>
+                        </el-form-item>
+                      </el-card>
+                    </div>
+                    <div v-if="item.contentType == 4">
+
+                    </div>
+                    <div v-if="item.contentType == 5 ">
+
+                      <el-form-item label="上传文件:" prop="fileUrl" label-width="100px">
+                        <el-upload
+                          v-model="item.fileUrl"
+                          class="avatar-uploader"
+                          :action="uploadUrl"
+                          :show-file-list="false"
+                          :on-success="(res, file) => handleAvatarSuccessFile(res, file, item)"
+                          :before-upload="beforeAvatarUploadFile">
+                          <i class="el-icon-plus avatar-uploader-icon"></i>
+                        </el-upload>
+                        <el-link v-if="item.fileUrl" type="primary" :href="downloadUrl(item.fileUrl)" download>
+                          {{ item.fileUrl }}
+                        </el-link>
+                      </el-form-item>
+
+                    </div>
+
+                    <div v-if="item.contentType == 6 ">
+                      <el-form-item label="上传视频:" prop="videoUrl" label-width="100px">
+                        <el-upload
+                          v-model="item.videoUrl"
+                          class="avatar-uploader"
+                          :action="uploadUrl"
+                          :show-file-list="false"
+                          :on-success="(res, file) => handleAvatarSuccessVideo(res, file, item)"
+                          :before-upload="beforeAvatarUploadVideo">
+                          <i class="el-icon-plus avatar-uploader-icon"></i>
+                        </el-upload>
+                        <video v-if="item.videoUrl"
+                               :src="item.videoUrl"
+                               controls style="width: 200px;height: 100px">
+                        </video>
+                      </el-form-item>
+                    </div>
+                    <div v-if="item.contentType == 7 ">
+                      <el-input
+                        v-model="item.value"
+                        type="textarea" :rows="3" maxlength="66" show-word-limit
+                        placeholder="输入要转为语音的内容" style="width: 90%;margin-top: 10px;"
+                        @input="handleInputVideoText(item.value,item)"/>
+                    </div>
+                    <div v-if="item.contentType == 8">
+
+                    </div>
+
+                  </el-form-item>
+                </el-form>
+              </el-col>
+              <el-col :span="1" :offset="1">
+                <i class="el-icon-delete" @click="delSetList(index,1)" style="margin-top: 20px;"
+                   v-if="setting.length>1"></i>
+              </el-col>
+            </el-row>
+          </div>
+          <el-link type="primary" class="el-icon-plus" :underline="false" @click='addSetList(1)'>
+            添加内容
+          </el-link>
+        </el-form-item>
+        <el-form-item label="全选销售" prop="isAllCompanyUser" v-if="!form.id">
+          <el-switch
+            v-model="form.isAllCompanyUser"
+            active-color="#13ce66"
+            inactive-color="#ff4949"
+            :active-value="1"
+            :inactive-value="2">
+          </el-switch>
+          <span v-if="form.isAllCompanyUser == '1'" style="margin-left: 10px;color: #13ce66">是</span>
+          <span v-else style="margin-left: 10px;color: #ff4949">否</span>
+        </el-form-item>
+        <el-form-item label="所属销售" prop="companyUserIds" v-if="!form.id">
+          <el-select v-model="companyUserIds" remote multiple placeholder="请选择" filterable style="width: 100%;">
+            <el-option
+              v-for="dict in userList"
+              :key="dict.userId"
+              :label="dict.nickName"
+              :value="dict.userId.toString()">
+            </el-option>
+          </el-select>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listCourseFinishTempParent, getCourseFinishTempParent, delCourseFinishTempParent, addCourseFinishTempParent, updateCourseFinishTempParent, exportCourseFinishTempParent } from "@/api/course/courseFinishTempParent";
+import {courseList} from '@/api/qw/sop'
+import ImageUpload from '@/views/qw/sop/ImageUpload.vue'
+import { getUserList } from '@/api/company/companyUser'
+
+
+export default {
+  name: "CourseFinishTempParent",
+  components: { ImageUpload },
+  data() {
+    return {
+      voiceLoading: false,
+      uploadUrl: process.env.VUE_APP_BASE_API + "/common/uploadOSS2",
+      uploadUrlByVoice: process.env.VUE_APP_BASE_API + "/common/uploadOSSByHOOKVoice",
+      // 遮罩层
+      loading: true,
+      // 导出遮罩层
+      exportLoading: false,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 完课模板表格数据
+      courseFinishTempParentList: [],
+      companyUserIds: [],
+      courseList: [],
+      userList: [],
+      // 状态字典
+      statusOptions: [],
+      allowSelect: [],
+      sysFsSopWatchStatus: [],
+      sysQwSopAiContentType: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      // 模板表格数据
+      setting: [],
+      chatSetting: [],
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        name: null,
+        courseId: null,
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+        name:[
+          { required: true, message: "名称不能为空", trigger: "blur" }
+        ],
+        courseId:[
+          { required: true, message: "课程不能为空", trigger: "blur" }
+        ],
+      }
+    };
+  },
+  created() {
+    this.getDicts("sys_company_status").then(response => {
+      this.statusOptions = response.data;
+    });//复用一下
+    this.getDicts("sys_qw_allow_select").then(response => {
+      this.allowSelect = response.data;
+    });
+
+    this.getDicts("sys_fs_sop_watch_status").then(response => {
+      this.sysFsSopWatchStatus = response.data;
+    });
+
+    this.getDicts("sys_qwSopAi_contentType").then(response => {
+      this.sysQwSopAiContentType = response.data;
+    });
+    getUserList().then(response => {
+      this.userList = response.data;
+    });
+    courseList().then(response => {
+      this.courseList = response.list;
+    });
+    this.getList();
+  },
+  methods: {
+    /** 查询完课模板列表 */
+    getList() {
+      this.loading = true;
+      listCourseFinishTempParent(this.queryParams).then(response => {
+        this.courseFinishTempParentList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        id: null,
+        status: 1,
+        name: null,
+        setting: [],
+        chatSetting: [],
+        courseId: null,
+        createTime: null,
+        createBy: null,
+        updateBy: null,
+        updateTime: null,
+        companyUserIds: null,
+        remark: null
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "添加完课模板";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getCourseFinishTempParent(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改完课模板";
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            updateCourseFinishTempParent(this.form).then(response => {
+              this.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            if (this.form.isAllCompanyUser == null) {
+              this.form.isAllCompanyUser = 2;
+            }
+            this.form.companyUserIds = this.companyUserIds.toString()
+
+            this.form.setting = JSON.stringify(this.setting)
+            this.form.chatSetting = JSON.stringify(this.chatSetting)
+
+            if (this.setting.length <= 0) {
+              return this.$message("请添加规则")
+            }
+            for (let i = 0; i < this.setting.length; i++) {
+              if (this.setting[i].contentType == 1 && (this.setting[i].value == null || this.setting[i].value == "")) {
+                return this.$message.error("内容不能为空")
+              }
+              if (this.setting[i].contentType == 2 && (this.setting[i].imgUrl == null || this.setting[i].imgUrl == "")) {
+                return this.$message.error("图片不能为空")
+              }
+              if (this.setting[i].contentType == 3 && (this.setting[i].linkTitle == null || this.setting[i].linkTitle == "")) {
+                return this.$message.error("链接标题不能为空")
+              }
+              if (this.setting[i].contentType == 3 && (this.setting[i].linkDescribe == null || this.setting[i].linkDescribe == "")) {
+                return this.$message.error("链接描述不能为空")
+              }
+              if (this.setting[i].contentType == 3 && (this.setting[i].linkImageUrl == null || this.setting[i].linkImageUrl == "")) {
+                return this.$message.error("链接图片不能为空")
+              }
+              if (this.setting[i].contentType == 3 && this.setting[i].type == 1 && (this.setting[i].linkUrl == null || this.setting[i].linkUrl == "")) {
+                return this.$message.error("链接地址不能为空")
+              }
+              if (this.setting[i].contentType == 5 && (this.setting[i].fileUrl == null || this.setting[i].fileUrl == "")) {
+                return this.$message.error("文件不能为空")
+              }
+              if (this.setting[i].contentType == 6 && (this.setting[i].videoUrl == null || this.setting[i].videoUrl == "")) {
+                return this.$message.error("视频不能为空")
+              }
+              if (this.setting[i].contentType == 7 && (this.setting[i].value == null || this.setting[i].value == "")) {
+                return this.$message.error("语音不能为空")
+              }
+            }
+            addCourseFinishTempParent(this.form).then(response => {
+              this.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$confirm('是否确认删除完课模板编号为"' + ids + '"的数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return delCourseFinishTempParent(ids);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess("删除成功");
+        }).catch(() => {});
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      const queryParams = this.queryParams;
+      this.$confirm('是否确认导出所有完课模板数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(() => {
+          this.exportLoading = true;
+          return exportCourseFinishTempParent(queryParams);
+        }).then(response => {
+          this.download(response.msg);
+          this.exportLoading = false;
+        }).catch(() => {});
+    },
+
+
+    handleAvatarSuccessFile(res, file, item) {
+      if (res.code === 200) {
+        // 使用 $set 确保响应式更新
+        this.$set(item, 'fileUrl', res.url);
+      } else {
+        this.msgError(res.msg);
+      }
+    },
+
+    beforeAvatarUploadFile(file) {
+      const isLt1M = file.size / 1024 / 1024 < 10;
+      if (!isLt1M) {
+        this.$message.error('上传大小不能超过 10MB!');
+      }
+      return isLt1M;
+    },
+    //下载文件
+    downloadUrl(materialUrl) {
+      // 直接返回文件 URL
+      return materialUrl;
+    },
+    handleInputVideoText(value, content) {
+      // 允许的字符:中文、英文(大小写)、数字和指定标点符号(,。!?)
+      const regex = /^[\u4e00-\u9fa5,。!?,!?]+$/;
+
+      // 删除不符合条件的字符
+      const filteredValue = value.split('').filter(char => regex.test(char)).join('');
+
+      this.$set(content, 'value', filteredValue);
+
+    },
+    handleAvatarSuccessVideo(res, file, item) {
+      if (res.code == 200) {
+        // 使用 $set 确保响应式更新
+        this.$set(item, 'videoUrl', res.url);
+      } else {
+        this.msgError(res.msg);
+      }
+    },
+
+    beforeAvatarUploadVideo(file) {
+      const isLt30M = file.size / 1024 / 1024 < 10;
+      const isMP4 = file.type === 'video/mp4';
+
+      if (!isMP4) {
+        this.$message.error('仅支持上传 MP4 格式的视频文件!');
+        return false;
+      }
+
+      if (!isLt30M) {
+        this.$message.error('上传大小不能超过 10MB!');
+        return false;
+      }
+
+      return true;
+    },
+
+    delSetList(index, type) {
+      if (type == 0) {
+        this.setting.splice(index, 1)
+      } else {
+        this.chatSetting.splice(index, 1)
+      }
+    },
+    addSetList(type) {
+      const newSetting = {
+        contentType: '1',
+        value: '',
+      };
+      // 将新设置项添加到 content.setting 数组中
+      if (type == 0) {
+        this.setting.push(newSetting);
+      } else {
+        this.chatSetting.push(newSetting);
+      }
+    },
+    jump(id){
+      this.$router.push('/qw/conversion/courseFinishTemp/' + id)
+    },
+  },
+};
+</script>

+ 10 - 2
src/views/qw/friendWelcome/indexNew.vue

@@ -917,6 +917,8 @@ export default {
       };
       if (item.msgtype === 'image') {
         this.fileFrom.imagePicUrl = item.image.pic_url;
+      }else if (item.msgtype === 'video') {
+        this.fileFrom.videoUrl = item.video.url;
       } else if (item.msgtype === 'link') {
         this.fileFrom.linkTitle = item.link.title;
         this.fileFrom.linkPicUrl = item.link.picurl;
@@ -985,7 +987,6 @@ export default {
 
     //提交附件
     confirmUpload(fileFrom) {
-
       const { type, index, itemIndex } = this.welcomeItem;
       let attachment = {};
       if (type === 'image') {
@@ -995,6 +996,13 @@ export default {
             pic_url: this.fileFrom.imagePicUrl
           }
         };
+      } else if (type === 'video') {
+        attachment = {
+          msgtype: 'video',
+          video: {
+            url:this.fileFrom.videoUrl,
+          }
+        };
       } else if (type === 'link') {
         attachment = {
           msgtype: 'link',
@@ -1298,7 +1306,7 @@ export default {
     handleAvatarSuccessVideo(res, file, content) {
       if (res.code == 200) {
         // 使用 $set 确保响应式更新
-        this.$set(content, 'videoUrl', res.url);
+        this.$set(content, 'videoUrl', "https://" + res.url);
       } else {
         this.msgError(res.msg);
       }

+ 46 - 58
src/views/qw/sop/addSop.vue

@@ -7,30 +7,19 @@
         <el-form-item label="规则名称" prop="name">
           <el-input v-model="form.name" placeholder="请输入规则名称"/>
         </el-form-item>
-
-        <el-form-item label="状态" prop="status">
-          <dict-tag :options="statusOptions" :value="form.status"></dict-tag>
-        </el-form-item>
-        <!--        <el-form-item label="状态">-->
-        <!--          <el-radio-group v-model="form.status">-->
-        <!--            <el-radio-->
-        <!--              v-for="dict in statusOptions"-->
-        <!--              :key="dict.dictValue"-->
-        <!--              :label="parseInt(dict.dictValue)"-->
-        <!--            >{{dict.dictLabel}}</el-radio>-->
-        <!--          </el-radio-group>-->
-        <!--        </el-form-item>-->
         <el-form-item label="类别" prop="type">
           <el-radio-group v-model="form.type" @change="clearUser">
-<!--            <el-radio-->
-<!--              :label="1"-->
-<!--            >个微-->
-<!--            </el-radio>-->
+            <!--            <el-radio-->
+            <!--              :label="1"-->
+            <!--            >个微-->
+            <!--            </el-radio>-->
+
             <el-radio
               :label="2"
             >企微
             </el-radio>
           </el-radio-group>
+          <Tip title="针对于企业微信平台" />
         </el-form-item>
 
 
@@ -45,21 +34,17 @@
             >群聊
             </el-radio>
           </el-radio-group>
-          <el-alert
-            title="群聊:模板每天第一条规则将发送到群聊里面,其余消息发送到个人"
-            type="info"
-            style="font-size: 15px; margin-top: 0;"
-            :closable="false"
-            show-icon>
-          </el-alert>
+          <Tip :title="'标签:根据企微客户的标签筛选客户进入SOP\r\n群聊:选择企微用户所属的群聊,并且只能选择课程模板,课程模板里面第一条规则是发送到群聊,其他规则催课会发送到群里面的个人'" />
         </el-form-item>
         <el-form-item label="小转天数" prop="minConversionDay" v-if="form.filterMode == 1">
           <!--          <el-input class="el-input" type="" v-model="form.minConversionDay" placeholder="请输入" />-->
           <el-input-number v-model="form.minConversionDay" :min="1" :max="100"></el-input-number>
+          <Tip title="第一次提醒销售,去联系客户,在【催课看板】处显示,哪些需要联系的客户" />
         </el-form-item>
         <el-form-item label="大转天数" prop="maxConversionDay" v-if="form.filterMode == 1">
           <!--          <el-input class="el-input" v-model="form.maxConversionDay" placeholder="请输入" />-->
           <el-input-number v-model="form.maxConversionDay" :min="1" :max="100"></el-input-number>
+          <Tip title="第二次提醒销售,去联系客户,在【催课看板】处显示,哪些需要联系的客户" />
         </el-form-item>
         <el-form-item label="选择员工" prop="qwUserIds" style="margin-top: 2%" v-if="form.filterMode == 2">
           <div>
@@ -83,11 +68,25 @@
                     v-if="list.id==id">{{ list.qwUserName }}</span>
             </el-tag>
           </div>
+          <Tip title="企业微信员工账号" />
         </el-form-item>
         <el-form-item label="群聊" prop="chatIds" v-if="form.filterMode == 2">
           <el-select multiple filterable clearable v-model="form.chatIds">
             <el-option v-for="item in qwGroupList" :key="item.chatId" :label="item.name" :value="item.chatId"/>
           </el-select>
+          <Tip title="选择的企业微信员工下面的群聊" />
+        </el-form-item>
+        <el-form-item label="客户评级" prop="isRating" style="margin-top: 2%">
+          <el-switch
+            v-model="form.isRating"
+            active-color="#13ce66"
+            inactive-color="#ff4949"
+            :active-value="1"
+            :inactive-value="2">
+          </el-switch>
+          <span v-if="form.isRating == '1'" style="margin-left: 10px;color: #13ce66">已开启</span>
+          <span v-if="form.isRating == '2'" style="margin-left: 10px;color: #ff4949">已关闭</span>
+          <Tip title="根据客户的【看课记录】进行评级,新进客户前4天不评级,第5天开始 根据客户近7天的看课记录进行评级 ABCD级" />
         </el-form-item>
         <div v-if="form.type==2 && form.filterMode == 1">
           <el-form-item label="推送方式 ">
@@ -99,6 +98,7 @@
               >{{ dict.dictLabel }}
               </el-radio>
             </el-radio-group>
+            <Tip title="选择模板类型" />
           </el-form-item>
           <el-form-item label="选择员工" prop="qwUserIds" style="margin-top: 2%">
             <div>
@@ -122,17 +122,7 @@
                       v-if="list.id==id">{{ list.qwUserName }}</span>
               </el-tag>
             </div>
-          </el-form-item>
-          <el-form-item label="客户评级" prop="isRating" style="margin-top: 2%">
-            <el-switch
-              v-model="form.isRating"
-              active-color="#13ce66"
-              inactive-color="#ff4949"
-              :active-value="1"
-              :inactive-value="2">
-            </el-switch>
-            <span v-if="form.isRating == '1'" style="margin-left: 10px;color: #13ce66">已开启</span>
-            <span v-if="form.isRating == '2'" style="margin-left: 10px;color: #ff4949">已关闭</span>
+            <Tip title="选择的企业微信员工下面的群聊" />
           </el-form-item>
           <el-form-item label="标签规则" prop="filterType">
             <el-radio-group v-model="form.filterType">
@@ -145,6 +135,7 @@
               >含任意标签
               </el-radio>
             </el-radio-group>
+            <Tip :title="'含全部标签:客户要完全一对一匹配上选择标签,ps:多一个少一个都不行 \r\n含任意标签:客户只要有一个标签匹配上即可'" />
           </el-form-item>
           <el-form-item label="选择的标签" prop="tags">
             <!--            <el-select v-model="tags" remote multiple placeholder="请选择" filterable  style="width: 100%;">-->
@@ -168,7 +159,7 @@
                 </el-tag>
               </div>
             </div>
-
+            <Tip title="选择进入SOP任务的标签" />
           </el-form-item>
           <el-form-item label="排除的标签" prop="excludeTags">
             <!--            <el-select v-model="excludeTags" remote multiple placeholder="请选择" filterable  style="width: 100%;">-->
@@ -191,7 +182,7 @@
                 >{{ list.name }}
                 </el-tag>
               </div>
-            </div>
+            </div><Tip title="选择不想进入SOP的标签" />
           </el-form-item>
         </div>
         <div v-if="form.type==1">
@@ -255,6 +246,7 @@
             >否
             </el-radio>
           </el-radio-group>
+          <Tip title="如果为固定营期,不管什么时候进入SOP的客户,营期时间都为SOP任务开始时间" />
         </el-form-item>
 
         <el-form-item label="开始时间" prop="startTime">
@@ -264,14 +256,16 @@
                           value-format="yyyy-MM-dd"
                           placeholder="选择开始时间">
           </el-date-picker>
+          <Tip title="SOP开始发送时间" />
         </el-form-item>
         <el-form-item label="任务过期时间" prop="expiryTime">
           <el-row>
             <el-input-number v-model="form.expiryTime" :min="1" :max="100"></el-input-number>
             (小时)
           </el-row>
+          <Tip title="任务生成的代发送消息,如果超过此设置的时间还未发送,自动作废" />
         </el-form-item>
-        <el-form-item v-if="(form.sendType==2 || form.sendType==4) && form.type != 3" label="自动添加SOP"
+        <el-form-item v-if="(form.sendType==2 || form.sendType==4) && form.type != 3 && form.isFixed == 0" label="自动添加SOP"
                       prop="autoSopTime.autoSopType">
           <el-radio-group v-model="form.autoSopTime.autoSopType">
             <el-radio
@@ -283,17 +277,10 @@
             >次日开始
             </el-radio>
           </el-radio-group>
+          <Tip :title="'这个选项仅作用于【新客户】进线时或【给客户打标签时】,是进入当日的营期 还是 次日的营期'" />
         </el-form-item>
-        <el-alert
-          v-if="form.autoSopTime.autoSopType==1"
-          title="起始时间-结束时间之内的,当天立即创建SOP,时间之外的 次日创建SOP"
-          type="warning"
-          style="font-size: 15px; margin-top: 0;"
-          :closable="false"
-          show-icon>
-        </el-alert>
         <div style="display: flex; align-items: center; flex-wrap: nowrap;">
-          <div v-if="form.autoSopTime.autoSopType==1" style="display: flex; align-items: center">
+          <div v-if="form.autoSopTime.autoSopType==1 && form.isFixed == 0" style="display: flex; align-items: center">
             <el-form-item
               label="起始时间"
               prop="autoStartTime"
@@ -355,6 +342,7 @@
             >否
             </el-radio>
           </el-radio-group>
+          <Tip title="是否只发送在平台注册了会员的客户" />
         </el-form-item>
 
         <el-form-item label="模板" prop="tempId">
@@ -365,6 +353,7 @@
             </el-tag>
             <span v-else style="margin: 3px; color: #999;">请点我选择模板</span>
           </div>
+          <Tip title="选择想要发送的模板规则" />
         </el-form-item>
       </el-form>
       <div slot="footer" class="dialog-footer" style="float: right;">
@@ -425,24 +414,23 @@
 </template>
 
 <script>
-import {listSop, getSop, delSop, addSop, updateSop, exportSop, courseList, videoList} from "@/api/qw/sop";
-import {listSopTemp, getSopTemp, delSopTemp, addSopTemp, updateSopTemp, exportSopTemp} from "@/api/qw/sopTemp";
-import {getQwAllUserList, listUser, qwList} from '@/api/company/companyUser'
+import { addSop, courseList, updateSop } from '@/api/qw/sop'
+import { getQwAllUserList, listUser } from '@/api/company/companyUser'
 import qwUserList from '@/views/qw/user/qwUserList.vue'
 import companyUserList from '@/views/company/companyUser/companyUserList.vue'
-import ImageUpload from "@/views/qw/sop/ImageUpload";
+import ImageUpload from '@/views/qw/sop/ImageUpload'
 import CustomerGroupDetails from '@/views/qw/groupMsg/customerGroupDetails.vue'
 import sopLogsDetails from '@/views/qw/sopLogs/sopLogsList.vue'
-import {listTag, getTag,} from "@/api/qw/tag";
-import {listWxUserGroup, sopListWxUserGroup} from "@/api/wxUser/wxUserGroup";
-import {allList, listAll as chatListAll} from "@/api/qw/groupChat";
-import SopTemp from "@/views/qw/sopTemp/sopTemp.vue";
-import {allListTagGroup} from "@/api/qw/tagGroup";
-import {getMyQwCompanyList} from "@/api/qw/user";
+import { listTag } from '@/api/qw/tag'
+import { sopListWxUserGroup } from '@/api/wxUser/wxUserGroup'
+import { listAll as chatListAll } from '@/api/qw/groupChat'
+import SopTemp from '@/views/qw/sopTemp/sopTemp.vue'
+import { allListTagGroup } from '@/api/qw/tagGroup'
+import Tip from '@/components/Tip'
 
 export default {
   name: "addSop",
-  components: {SopTemp, CustomerGroupDetails, qwUserList, companyUserList, ImageUpload, sopLogsDetails},
+  components: {SopTemp, CustomerGroupDetails, qwUserList, companyUserList, ImageUpload, sopLogsDetails, Tip},
   data() {
     return {
       //模板查询