当前位置:   article > 正文

微信小程序 讯飞录音 点击按钮录音内容转文字

微信小程序 讯飞录音 点击按钮录音内容转文字

  1. <page-meta page-style="{{ showPolish ? 'overflow: hidden;' : '' }}" />
  2. <view class="wrap">
  3. <view class="header-tab" style="justify-content: {{typeList.length > 2 ? 'start' : 'center'}}">
  4. <view class="tab-list {{idx == item.id ? 'active' : ''}}" wx:for="{{typeList}}" wx:key="id" data-scene="{{item.scene}}" data-idx="{{item.id}}" data-ext="{{item.ext}}" bindtap="tabHandle">
  5. <image src="{{item.thumb}}" class="icon-daily" mode="aspectFill" />
  6. <view class="v1">{{item.name}}</view>
  7. </view>
  8. <!-- <view class="tab-list v2 {{idx == '2' ? 'active' : ''}}" data-idx="2" bindtap="tabHandle">
  9. <image src="/image/outdoors.png" class="icon-daily" mode="widthFix"/>
  10. </view>
  11. <view class="tab-list {{idx == '3' ? 'active' : ''}}" data-idx="3" bindtap="tabHandle">
  12. <image src="/image/mixedcollar.png" class="icon-daily" mode="widthFix"/>
  13. </view> -->
  14. </view>
  15. <!--如果是管理员-->
  16. <block wx:if="{{isAdmin || isSeniorTeacher || isTeacherDirector}}">
  17. <scroll-view class="scroll-class-box" scroll-x="true">
  18. <view class="scroll-class-list {{classCheckedId == item.classId ? 'active': ''}}" wx:for="{{classData}}" wx:key="id" data-index="{{index}}" data-id="{{item.classId}}" bindtap="checkClassHandle">
  19. {{item.className}}
  20. </view>
  21. </scroll-view>
  22. </block>
  23. <!--指向主题活动-->
  24. <view class="white-box record-white-box" wx:if="{{themeExt}}">
  25. <view class="title-box">
  26. <view class="yellow-fence"></view>
  27. <view class="title-txt-part">
  28. <view class="v1">指向主题活动</view>
  29. </view>
  30. <view class="close-box" bindtap="openThemeHandle">
  31. <image src="{{openTheme ? '/image/icon_arrow_up2.png' : '/image/icon_arrow_down2.png'}}" data-idx="{{index}}" class="icon-close-black"></image>
  32. </view>
  33. </view>
  34. <block wx:if="{{openTheme}}">
  35. <view class="theme-item" wx:if="{{activityList.length > 0}}">
  36. <view class="theme-list" wx:for="{{activityList}}" wx:key="id" data-idx="{{index}}" bindtap="checkActivityHandle">
  37. <image src="{{item.checked?'/image/icon_checkbox_checked.png':'/image/icon_checkbox.png'}}" class="icon-checkbox"></image>
  38. <view class="v1">{{item.name}}</view>
  39. <view class="v2">{{item.status == '1' ? '整理' : '计划'}}{{item.monthWeek ? item.monthWeek : '-暂无'}}</view>
  40. </view>
  41. <view class="package-footer" bindtap="loadMoreActivity">{{moreTxt}}</view>
  42. <view class="up-box mt20" bindtap="openThemeHandle">
  43. <image src="/image/icon_arrow_up2.png" class="icon-close-black"></image>
  44. </view>
  45. </view>
  46. <block wx:else>
  47. <view class="close-box-str" bindtap="openThemeHandle">暂未安排活动 | 计划-无</view>
  48. </block>
  49. </block>
  50. <view class="close-box-str" wx:if="{{!openTheme}}" bindtap="openThemeHandle">{{themeStr ? themeStr : '未选择相关主题活动'}}</view>
  51. </view>
  52. <!--选择幼儿-->
  53. <view class="white-box record-white-box">
  54. <view class="title-box">
  55. <view class="yellow-fence"></view>
  56. <view class="title-txt-part">
  57. <view class="v1">
  58. 选择幼儿
  59. <text class="t1">*</text>
  60. </view>
  61. <view class="student-number">已选择{{checkedStudentsTreated.length}}个幼儿</view>
  62. </view>
  63. <view class="close-box" bindtap="openStudentHandle">
  64. <image src="{{openStudents ? '/image/icon_arrow_up2.png' : '/image/icon_arrow_down2.png'}}" data-idx="{{index}}" class="icon-close-black"></image>
  65. </view>
  66. </view>
  67. <!--名字保留四个字-->
  68. <block wx:if="{{openStudents}}">
  69. <view class="student-box" wx:if="{{students.length > 0}}">
  70. <view class="student-list" wx:for="{{students}}" wx:key="id" data-idx="{{index}}" bindtap="checkHandle">
  71. <image src="/image/icon_check.png" class="icon-check" wx:if="{{item.checked}}" />
  72. <image src="{{item.studentImage ? item.studentImage : '/image/default.png'}}" mode="aspectFill" class="student-photo" />
  73. <view class="v1">{{item.studentNumber}}号-{{item.studentName}}</view>
  74. </view>
  75. </view>
  76. <view class="up-box" bindtap="openStudentHandle" wx:if="{{students.length > 0}}">
  77. <image src="/image/icon_arrow_up2.png" class="icon-close-black"></image>
  78. </view>
  79. <block wx:if="{{students.length == 0}}">
  80. <view class="close-box-str">还未录入本班幼儿信息,请去后台录入</view>
  81. </block>
  82. </block>
  83. <view class="student-box" wx:if="{{!openStudents && checkedStudents.length > 0}}" bindtap="openStudentHandle">
  84. <view class="student-list2" wx:for="{{checkedStudentsTreated}}" wx:key="id">
  85. <image src="{{item.studentImage ? item.studentImage : '/image/default.png'}}" mode="aspectFill" class="student-photo2" />
  86. <view class="v1">{{item.studentNumber}}号-{{item.studentName}}</view>
  87. </view>
  88. <view class="student-list2" wx:if="{{checkedStudents.length > 10}}">
  89. <view class="more-box">...</view>
  90. </view>
  91. </view>
  92. <view class="no-graphs" wx:if="{{!openStudents && students.length > 0 && checkedStudents.length == 0}}" bindtap="openStudentHandle">未选择幼儿</view>
  93. </view>
  94. <!--记录日期-->
  95. <view class="white-box record-white-box only-box">
  96. <view class="title-box">
  97. <view class="yellow-fence"></view>
  98. <view class="title-txt-part">
  99. <view class="v1">记录日期<text class="t1">*</text></view>
  100. </view>
  101. </view>
  102. <view class="check-list-rig">
  103. <picker mode="date" bindchange="bindDateChange" value="{{selectedDate}}">
  104. <view class="picker">
  105. {{selectedDate ? selectedDate : '日期未选'}}
  106. </view>
  107. </picker>
  108. </view>
  109. </view>
  110. <!--观察场景-->
  111. <view class="white-box record-white-box only-box">
  112. <view class="title-box">
  113. <view class="yellow-fence"></view>
  114. <view class="title-txt-part">
  115. <view class="v1">观察场景<text class="t1">*</text></view>
  116. </view>
  117. </view>
  118. <view class="check-list-rig">
  119. <picker mode="selector" range="{{observeSceneList}}" bindchange="bindParentChange" value="{{observeParentIndex}}" range-key="expenseItem">
  120. <view class="picker">
  121. {{observeSceneList[observeParentIndex].expenseItem}}
  122. </view>
  123. </picker>
  124. <view class="ones-aline">-</view>
  125. <picker mode="selector" range="{{childArray}}" bindchange="bindChildChange" value="{{observeChildIndex}}" range-key="expenseItem">
  126. <view class="picker">
  127. {{childArray[observeChildIndex].expenseItem}}
  128. </view>
  129. </picker>
  130. </view>
  131. </view>
  132. <!--观察目的-->
  133. <view class="white-box record-white-box">
  134. <view class="title-box">
  135. <view class="yellow-fence"></view>
  136. <view class="title-txt-part">
  137. <view class="v1">观察目的</view>
  138. </view>
  139. <!-- <view class="close-box" bindtap="openObserveHandle">
  140. <image src="{{openObserve ? '/image/icon_arrow_up2.png' : '/image/icon_arrow_down2.png'}}" data-idx="{{index}}" class="icon-close-black"></image>
  141. </view> -->
  142. </view>
  143. <view class="observe-cont mt-20">
  144. <view class="textarea-wrap">
  145. <textarea class="textarea-box2" value="{{observe}}" placeholder="" maxlength="500" bindinput="monitorObserveInput" style="border-radius: 10rpx 10rpx 0 0;"></textarea>
  146. <!-- <view class="ai-wrap">
  147. <view class="v1" data-aistyle="1" bindtap="aimAiHandle">
  148. <image src="/image/ai.png" class="icon-ai" />
  149. <view class="v1">AI续写</view>
  150. </view>
  151. </view> -->
  152. <view class="textarea-foot">
  153. <view class="textarea-foot-lef">已输入{{observeNumber}}个字</view>
  154. <view class="textarea-foot-rig">{{observeNumber}}/500</view>
  155. </view>
  156. </view>
  157. </view>
  158. <!--如果时间 主题 textarea都是空的 则显示 暂无观察情境-->
  159. <!-- <view class="close-box-str" wx:if="{{!openObserve}}" bindtap="openObserveHandle">{{observeStr ? observeStr : '未设相关信息'}}</view> -->
  160. </view>
  161. <!--观察记录-->
  162. <view class="white-box record-white-box" wx:for="{{activityMaterials}}" wx:key="index">
  163. <view class="title-box">
  164. <view class="yellow-fence"></view>
  165. <view class="title-txt-part">
  166. <view class="v1">观察记录<text class="t1">*</text></view>
  167. </view>
  168. <image src="/image/close.png" data-idx="{{index}}" class="icon-close-black2" bindtap="deleteHandle" style="margin-right:9rpx"></image>
  169. </view>
  170. <view class="textarea-box-wrap">
  171. <view class="voice-box" wx:if="{{item.recordArr.length > 0}}">
  172. <view class="record-item" wx:for="{{item.recordArr}}" wx:key="txt" wx:for-item="oItem" wx:for-index="oIndex">
  173. <!--down:-160rpx up:90rpx-->
  174. <view class="pos-box" style="margin-top:{{oItem.directionUp?'-160':'90'}}rpx;" wx:if="{{oItem.showTip}}">
  175. <view class="pos-box-lef" data-pidx="{{index}}" data-idx="{{oIndex}}" bindtap="txtRecordHandle">
  176. <image src="/image/icon_txt.png" class="icon-txt" />
  177. <text class="t1">转文字</text>
  178. </view>
  179. <view class="pos-box-rig" data-pidx="{{index}}" data-idx="{{oIndex}}" bindtap="delRecordHandle">
  180. <image src="/image/icon_del.png" class="icon-del" />
  181. <text class="t1">删除</text>
  182. </view>
  183. <image src="/image/icon_arrow_down.png" wx:if="{{oItem.directionUp}}" class="icon-arrow-down" />
  184. <image src="/image/icon_arrow_up.png" wx:if="{{!oItem.directionUp}}" class="icon-arrow-up" />
  185. </view>
  186. <view class="record-list" data-pidx="{{index}}" data-idx="{{oIndex}}" bindtap="playHandle" bindlongpress="onLongPress">
  187. <image src="{{oItem.played == true ? '/image/icon_pause.png' : '/image/icon_video.png'}}" class="icon-video" />
  188. <text class="t1">语音</text>
  189. <text class="t2">00:{{oItem.time}}</text>
  190. </view>
  191. <view class="record-txt" wx:if="{{oItem.showTxt}}">{{oItem.txt}}</view>
  192. </view>
  193. </view>
  194. <textarea class="textarea-box" value="{{item.content}}" data-idx="{{index}}" bindinput="textareaBlurHandle" placeholder="请输入内容" maxlength="19999"></textarea>
  195. <view class="textarea-box-footer">
  196. <!-- <view class="ai-box" data-idx="{{index}}" data-aistyle="2" bindtap="recordAiHandle">
  197. <image src="/image/ai.png" class="icon-ai" />
  198. <view class="v1">AI续写</view>
  199. </view> -->
  200. <button class="record-btn" data-idx="{{index}}" bindtap="recordHandle">
  201. <image src="/image/icon_record_gray.png" wx:if="{{!item.recordState}}" class="icon-record" />
  202. <image src="/image/icon_record_red.png" wx:else="{{item.recordState}}" class="icon-record" />
  203. </button>
  204. </view>
  205. </view>
  206. <view class="material-box">
  207. <block wx:for="{{activityMaterials[index].material}}" wx:for-item="mItem" wx:for-index="mIndex" wx:key="url">
  208. <view class="material-list" wx:if="{{mItem.type == 'img'}}">
  209. <image src="/image/icon_close.png" class="icon-close" data-pidx="{{index}}" data-idx="{{mIndex}}" bindtap="closeHadle" />
  210. <image src="{{mItem.url}}" data-src="{{mItem.url}}" data-pidx="{{index}}" data-idx="{{mIndex}}" bindtap="preview" class="material-list-m2" mode="aspectFill"></image>
  211. </view>
  212. <view class="material-list" wx:if="{{mItem.type == 'mp4'}}">
  213. <image src="/image/icon_close.png" class="icon-close" data-pidx="{{index}}" data-idx="{{mIndex}}" bindtap="closeHadle" />
  214. <video src="{{mItem.url}}" data-src="{{mItem.url}}" class="material-list-m2" mode="aspectFill"></video>
  215. </view>
  216. </block>
  217. <button class="upload-box" data-idx="{{index}}" bindtap="uploadFile">
  218. <image src="/image/icon_photo.png" class="icon-photo" />
  219. 上传图片、视频
  220. </button>
  221. </view>
  222. </view>
  223. <view class="add-box" bindtap="addListHandle">
  224. <image src="/image/add.png" mode="widthFix" class="icon-add2" />添加新的图文描述
  225. </view>
  226. <!--幼儿发展水平评估-->
  227. <view class="white-box record-white-box">
  228. <view class="title-box">
  229. <view class="yellow-fence"></view>
  230. <view class="title-txt-part">
  231. <view class="v1">幼儿发展水平评估</view>
  232. </view>
  233. <view class="close-box" bindtap="openAreaHandle" wx:if="{{selectArea.length > 0}}">
  234. <image src="{{openArea ? '/image/icon_arrow_up2.png' : '/image/icon_arrow_down2.png'}}" data-idx="{{index}}" class="icon-close-black"></image>
  235. </view>
  236. </view>
  237. <block wx:if="{{openArea && selectArea.length > 0}}">
  238. <!--第一级-->
  239. <scroll-view class="scroll-box" scroll-x="true">
  240. <view class="domain-first {{areaFirstIndex == index ? 'active': ''}}" wx:for="{{selectArea}}" wx:key="id" data-index="{{index}}" data-id="{{item.id}}" bindtap="getSelectAreaId">
  241. {{item.name}}
  242. <block wx:if="{{item.checked}}">
  243. <image src="/image/corner_mark.png" class="corner-mark"></image>
  244. </block>
  245. </view>
  246. </scroll-view>
  247. <!--有可能消失的第二级 如果第一级的id用于查询指标列表 指标列表type是3 则第二级显示 如果type是4则该第二级隐藏 ***如果没有children 直接使用选项卡*** 第二级是单选-->
  248. <view class="domain-second" wx:if="{{showAreaSecond}}">
  249. <view class="domain-second-list {{areaSecondIndex == index ? 'active': ''}}" wx:for="{{listSelect}}" wx:key="id" data-index="{{index}}" bindtap="getAreaSecondIndex">{{item.label}}</view>
  250. </view>
  251. <!--必然存在的第三级 第三级的组成是title + list 第三级是子级单选 理论上有多个数组 多个数组有对应的子级-->
  252. <view class="domain-three" wx:if="{{showAreaSecond}}">
  253. <view class="domain-three-item" wx:for="{{threeData.children}}" wx:key="id">
  254. <view class="domain-three-title">
  255. <view class="v1">{{item.label}}</view>
  256. <view class="v2">(请在下方选择一个水平)</view>
  257. </view>
  258. <view class="domain-three-list" wx:for="{{item.children}}" wx:for-item="mItem" wx:for-index="mIndex" wx:key="id" data-parentindex="{{index}}" data-childindex="{{mIndex}}" data-item="{{mItem}}" bindtap="checkedAreaHandle">
  259. <image src="{{mItem.checked ? '/image/icon_checkbox_checked.png' : '/image/icon_checkbox.png'}}" class="icon-checkbox"></image>
  260. <view class="v2 {{mItem.checked ? 'active' : ''}}">{{mItem.label}}</view>
  261. </view>
  262. </view>
  263. </view>
  264. <!--type为4的时候-->
  265. <view class="domain-three" wx:else>
  266. <view class="domain-three-item" wx:for="{{threeData}}" wx:key="id">
  267. <view class="domain-three-title">
  268. <view class="v1">{{item.label}}</view>
  269. <view class="v2">(请在下方选择一个水平)</view>
  270. </view>
  271. <view class="domain-three-list" wx:for="{{item.children}}" wx:for-item="mItem" wx:for-index="mIndex" wx:key="id" wx:for-item="mItem" wx:for-index="mIndex" wx:key="id" data-parentindex="{{index}}" data-childindex="{{mIndex}}" data-item="{{mItem}}" bindtap="checkedAreaHandle">
  272. <image src="{{mItem.checked ? '/image/icon_checkbox_checked.png' : '/image/icon_checkbox.png'}}" class="icon-checkbox"></image>
  273. <view class="v2 {{mItem.checked ? 'active' : ''}}">{{mItem.label}}</view>
  274. </view>
  275. </view>
  276. </view>
  277. </block>
  278. <view wx:if="{{selectArea.length == 0}}">
  279. <view class="no-graphs">未做幼儿发展水平评估</view>
  280. </view>
  281. <view class="close-box-str" wx:if="{{!openArea && selectArea.length > 0}}" bindtap="openAreaHandle">{{areaStr ? areaStr : '暂无幼儿发展水平评估'}}</view>
  282. </view>
  283. <view class="white-box record-white-box">
  284. <view class="title-box">
  285. <view class="yellow-fence"></view>
  286. <view class="title-txt-part">
  287. <view class="v1">改进措施</view>
  288. </view>
  289. <!-- <view class="close-box">
  290. <image src="/image/icon_arrow_down2.png" data-idx="{{index}}" class="icon-close-black"></image>
  291. </view> -->
  292. </view>
  293. <view class="textarea-wrap" style="margin-top: 20rpx;">
  294. <textarea class="textarea-box2" value="{{measure}}" placeholder="" maxlength="500" bindinput="monitorMeasureInput"></textarea>
  295. <view class="textarea-foot">
  296. <view class="textarea-foot-lef">已输入{{measureNumber}}个字</view>
  297. <view class="textarea-foot-rig">{{measureNumber}}/500</view>
  298. </view>
  299. </view>
  300. </view>
  301. <!-- <view class="save-btn" bindtap="save">提交</view> -->
  302. <view class="white-box record-footer">
  303. <view class="footer">
  304. <view wx:if="{{!oid}}" class="v3" bindtap="cacelObserve">取消</view>
  305. <view wx:if="{{oid}}" class="v3" bindtap="deleteObserve">删除</view>
  306. <view class="v1" data-status="0" bindtap="save">暂存</view>
  307. <view class="v2" data-status="1" bindtap="save">提交</view>
  308. </view>
  309. </view>
  310. <view class="mask" wx:if="{{maskShow}}" bindtap="closeTipHandle"></view>
  311. <!--Ai弹窗-->
  312. <view class="ai-mask" wx:if="{{showPolish}}">
  313. <view class="ai-pop">
  314. <scroll-view class="ai-pop-cont" scroll-y="true">
  315. <textarea class="textarea-box2" value="{{aiPolish}}" placeholder="" maxlength="500" style="border-radius: 10rpx 10rpx 0 0;" bindinput="monitorPopInput"></textarea>
  316. </scroll-view>
  317. <view class="ai-pop-footer">
  318. <view class="v1" bindtap="aiCancel">取消</view>
  319. <view class="v2" bindtap="aiAgain">重写</view>
  320. <view class="v3" bindtap="aiConfirm">确定</view>
  321. </view>
  322. </view>
  323. </view>
  324. </view>
  1. const app = getApp()
  2. const util = require('../../utils/util.js');
  3. const api = require('../../config/api.js');
  4. const BASE_URL = app.globalData.BASE_URL
  5. let lock = false
  6. //获取当天的年月日用‘-’分隔
  7. function getDayDate() {
  8. const currentDate = new Date();
  9. const year = currentDate.getFullYear();
  10. const month = String(currentDate.getMonth() + 1).padStart(2, '0');
  11. const day = String(currentDate.getDate()).padStart(2, '0');
  12. return `${year}-${month}-${day}`;
  13. }
  14. const innerAudioContext = wx.createInnerAudioContext({
  15. useWebAudioImplement: false // 是否使用 WebAudio 作为底层音频驱动,默认关闭。对于短音频、播放频繁的音频建议开启此选项,开启后将获得更优的性能表现。由于开启此选项后也会带来一定的内存增长,因此对于长音频建议关闭此选项
  16. })
  17. const recorderManager = wx.getRecorderManager();
  18. var wxst; //语音websocket
  19. var status = 0; // 音频的状态
  20. var iatResult = [] // 识别结果
  21. const searchoptions = {
  22. duration: 1000 * 60,
  23. sampleRate: 16000,
  24. numberOfChannels: 1,
  25. encodeBitRate: 48000,
  26. format: 'mp3',
  27. frameSize: 6
  28. }
  29. Page({
  30. data: {
  31. idx: '1',
  32. students: [],
  33. activityMaterials: [],
  34. userInfo: {},
  35. oid: null, //跳转过来编辑的id
  36. //recordArr: [], recordArr率属于activityMaterials的子集 //音频数组 包含三个字段 url->mp3格式文件 txt:MP3的文字版的文本 time: 录音的时间 played:是否正在播放
  37. //录音部分-start
  38. parentIndex: null,
  39. maskShow: false, //透明的遮罩层
  40. srcMic: '',
  41. edit_text_max: 200,
  42. remain_length: 200,
  43. edit_text: "",
  44. is_focus: false,
  45. tips: "",
  46. index: -1,
  47. voicePath: "",
  48. //语音
  49. //recordState: false, //录音状态 该字段纳入作为activityMaterials的子级 由activityMaterials统一调配
  50. contentTxt: '', //内容
  51. firstSend: true,
  52. clientY: 0, //点击的地方到顶部的距离
  53. //录音部分-end
  54. activityId: null, //指向主题活动回显
  55. themeList: [], //指向主题活动
  56. themeChecked: {}, //主题选中
  57. themeStr: '', //指向主题活动关闭时候显示的文本
  58. openTheme: false, //指向主题活动开关
  59. checkedStudents: [], //选中的幼儿列表
  60. checkedStudentsTreated: [], //选中的幼儿处理过的列表 超过10个得截取成9个
  61. openStudents: false, //选择幼儿开关
  62. openObserve: false, //观察背景开关
  63. observeStr: '', //观察关闭时候显示的文本
  64. openArea: false, //幼儿发展水平评估开关
  65. areaStr: '', //幼儿发展水平评估关闭时候显示的文本
  66. observe: '', //观察目的
  67. observeNumber: 0,
  68. areaFirstIndex: 0, //一级选中的index 默认第一个选中
  69. areaSecondIndex: 0, //二级选中的index 默认第一个选中 如果type为3
  70. //selectArea: [], //评估对象列表
  71. showAreaSecond: false, //是否展示二级
  72. observationViewId: '', //编辑观察记录的id
  73. listSelect: [], //指标列表
  74. threeData: [], //三级列表数据
  75. evaluationItems: [], //幼儿发展水平评估最终存储的数组 也就是选中的数组
  76. activityList: [], //指向主题活动列表
  77. pageNum: 1,
  78. pageSize: 6,
  79. moreTxt: '点击加载更多',
  80. flag: false,
  81. selectedDate: getDayDate(),
  82. /*观察场景-start*/
  83. observeSceneList: [],
  84. childArray: [], // 子集数组
  85. observeParentIndex: 0, // 当前选中的父级索引
  86. observeChildIndex: 0, // 当前选中的子集索引
  87. /*观察场景-end*/
  88. measure: '', //改进措施
  89. measureNumber: 0,
  90. isAdmin: false, //判断是不是管理员
  91. isSeniorTeacher: false,//判断是不是超级教师
  92. isTeacherDirector: false,//判断是不是混龄教师
  93. classData: [],
  94. classCheckedId: '', //选中的classId 如果是管理员的时候 默认选中第一个 非管理员不调用
  95. typeList: [], //观察记录顶部tab
  96. sceneChecked: '', //观察场景选中对象
  97. themeExt: false, //指向主题活动是否显示
  98. //观察目的Ai续写
  99. aiPolish: '', //Ai续写的内容
  100. showPolish: false, //Ai续写弹窗
  101. aistyle: null, //1是观察目的 2是观察记录
  102. aiParentIndex: null, //观察记录 第几个在Ai续写
  103. aimAiPolish: '', //观察目的Ai续写的内容
  104. aimAiKeyword: '', //关键词
  105. },
  106. onLoad() {},
  107. onShow: function () {
  108. wx.setStorageSync('activtyTab', {}); //重置备课助手tab的条件
  109. wx.setStorageSync('activityAdminTab', {}); //ly-add 2023-10-09 重置主题活动列表管理员状态下的班级选中状态
  110. if (app.globalData.isActivityMaterials) return
  111. app.globalData.isActivityMaterials = false //重置记观察记录的上传状态
  112. lock = false;
  113. const userInfo = wx.getStorageSync('userInfo');
  114. //判断roles是不是'sch'判断当前用户是不是'园长' 如果roles是senior_teacher那么该角色和园长拥有相同'观察评价'权限 统计里也要和园长一样 也就是'观察记录'、'观察统计' 混龄账号目前不可能是超级老师 2024-04-16
  115. let isAdmin = false
  116. let isSeniorTeacher = false
  117. let isTeacherDirector = false
  118. if(userInfo.roleKeysString){
  119. let oarr = userInfo.roleKeysString.split(',')
  120. isAdmin = util.arrayContainsSch(oarr)
  121. isSeniorTeacher = util.arrayContainsSeniorteacher(oarr)
  122. isTeacherDirector = util.arrayContainsTeacherdirector(oarr)
  123. }
  124. this.setData({
  125. userInfo,
  126. isAdmin: isAdmin,//判断是不是管理员
  127. isSeniorTeacher: isSeniorTeacher,//判断是不是 超级教师
  128. isTeacherDirector: isTeacherDirector,//判断是不是混龄教师
  129. })
  130. this.loadRecord();
  131. this.selectClass(); //加载的时候 幼儿发展水平评估 走的这个方法
  132. //重置录音模块
  133. this.initRecord();
  134. this.resetObserve()
  135. },
  136. loadRecord() {
  137. var that = this;
  138. recorderManager.onStart(() => { //开始录音时触发
  139. status = 0;
  140. iatResult = []
  141. //console.log('recorder start');
  142. that.data.firstSend = false;
  143. });
  144. recorderManager.onError((res) => { //错误回调
  145. //console.log(res);
  146. });
  147. recorderManager.onStop((res) => { //结束录音时触发
  148. //console.log('recorder stop')
  149. //console.log(res)
  150. let otime = (res.duration / 1000).toFixed(0)
  151. status = 2;
  152. var sendsty = '{"data":{"status":2,"audio":"","format":"audio/L16;rate=8000","encoding":"raw"}}'
  153. wxst.send({
  154. data: sendsty
  155. })
  156. wx.uploadFile({
  157. // 模拟https
  158. url: BASE_URL + 'common/uploadMediaToTencent', //需要用HTTPS,同时在微信公众平台后台添加服务器地址
  159. filePath: res.tempFilePath, //上传的文件本地地址
  160. name: 'file',
  161. formData: {
  162. 'userId': wx.getStorageSync('userInfo').userId,
  163. 'scene': 'observation'
  164. },
  165. //附近数据,这里为路径
  166. success: function (result) {
  167. // console.log("--结束录音--")
  168. // console.log(that.data.contentTxt)
  169. // console.log(JSON.parse(result.data).url)
  170. // console.log(otime)
  171. if (that.data.contentTxt) {
  172. //recordArr: []//音频数组 包含三个字段 url->mp3格式文件 txt:MP3的文字版的文本 time: 录音的时间 played:是否正在播放
  173. let ourl = JSON.parse(result.data).url
  174. let pidx = that.data.parentIndex
  175. let params = {
  176. url: ourl,
  177. txt: that.data.contentTxt,
  178. time: that.timeHandle(otime), //这个时间是用来显示的
  179. played: false,
  180. showTxt: false, //语音的文字部分是否展示
  181. showTip: false, //Tooltip 文字提示是否展示
  182. directionUp: false, //Tooltip的方向是向上还是向下
  183. }
  184. let oarr = that.data.activityMaterials
  185. oarr.forEach((item) => {
  186. item.recordArr = item.recordArr && item.recordArr.length > 0 ? item.recordArr : []
  187. })
  188. oarr[pidx].recordArr.push(params)
  189. that.setData({
  190. activityMaterials: oarr
  191. })
  192. //console.log(that.data.activityMaterials)
  193. } else {
  194. //console.log("木有内容啊")
  195. }
  196. },
  197. fail: function (err) {
  198. //console.log(err)
  199. }
  200. })
  201. });
  202. recorderManager.onFrameRecorded((res) => { //每帧触发
  203. const that = this
  204. const {
  205. frameBuffer,
  206. isLastFrame
  207. } = res
  208. let params = {
  209. 'common': {
  210. 'app_id': '57198f05'
  211. },
  212. 'business': {
  213. 'language': 'zh_cn', //⼩语种可在控制台--语⾳听写(流式)--⽅⾔/语种处添加试⽤
  214. 'domain': 'iat',
  215. 'accent': 'mandarin', //中⽂⽅⾔可在控制台--语⾳听写(流式)--⽅⾔/语种处添加试⽤
  216. 'vad_eos': 1000,
  217. 'dwa': 'wpgs' //为使该功能⽣效,需到控制台开通动态修正功能(该功能免费)
  218. },
  219. 'data': {
  220. 'status': 0,
  221. 'format': 'audio/L16;rate=16000',
  222. 'encoding': 'lame',
  223. 'audio': wx.arrayBufferToBase64(frameBuffer)
  224. }
  225. }
  226. // 拼接数据
  227. let status = 0
  228. if (this.data.firstSend) {
  229. this.data.firstSend = false
  230. } else {
  231. if (isLastFrame) {
  232. status = 2
  233. } else {
  234. status = 1
  235. }
  236. }
  237. params.data.status = status
  238. wx.sendSocketMessage({
  239. data: JSON.stringify(params),
  240. success: (data) => {
  241. //console.log('send success:' + JSON.stringify(data))
  242. //that.resetRecordState()
  243. },
  244. fail: (err) => {
  245. //console.log('send error:' + JSON.stringify(err))
  246. //中断录音的时候
  247. //that.resetRecordState()
  248. },
  249. completed: () => {
  250. if (isLastFrame) {
  251. // wx closeSocket
  252. }
  253. }
  254. })
  255. })
  256. },
  257. resetObserve() {
  258. //选择领域模块
  259. this.setData({
  260. areaFirstIndex: 0,
  261. selectArea: [], //评估对象列表
  262. showAreaSecond: false, //是否展示二级
  263. observationViewId: '', //编辑观察记录的id
  264. listSelect: [], //指标列表
  265. idx: '1',
  266. openTheme: false, //指向主题活动开关
  267. themeStr: '', //指向主题活动关闭时候显示的文本
  268. openStudents: false,
  269. openObserve: false,
  270. openArea: false,
  271. observeStr: '',
  272. areaStr: '',
  273. evaluationItems: [],
  274. measureNumber: 0,
  275. observeParentIndex: 0,
  276. oid: app.globalData.isRecordEdit ? app.globalData.recordId : '', //判断是不是从报告页面跳转过来 如果是则赋值id
  277. measure: '',
  278. classData: [],
  279. classCheckedId: '', //选中的classId 如果是管理员的时候 默认选中第一个 非管理员不调用
  280. activityId: null,
  281. //选择幼儿-start
  282. checkedStudents: [],
  283. checkedStudentsTreated: [],
  284. students: [],
  285. studentArr: [],
  286. themeChecked: {},
  287. //选择幼儿-end
  288. //观察背景-start
  289. selectedDate: getDayDate(), //记录日期
  290. observeParentIndex: 0,
  291. observeChildIndex: 0,
  292. observe: '',
  293. observeNumber: 0,
  294. //观察背景-end
  295. activityMaterials: [{
  296. content: '',
  297. material: []
  298. }],
  299. typeList: [], //观察记录顶部tab
  300. sceneChecked: '', //观察场景选中对象
  301. themeExt: false, //指向主题活动是否显示
  302. //观察目的Ai续写
  303. aiPolish: '', //Ai续写的内容
  304. showPolish: false, //Ai续写弹窗
  305. aistyle: null, //1是观察目的 2是观察记录
  306. aiParentIndex: null, //观察记录 第几个在Ai续写
  307. aimAiPolish: '', //观察目的Ai续写的内容
  308. aimAiKeyword: '', //关键词
  309. })
  310. if (this.data.oid) {
  311. this.loadData()
  312. }
  313. },
  314. //回显数据
  315. loadData() {
  316. const that = this;
  317. util.request(api.observeDetail + this.data.oid, '', 'get').then(res => {
  318. if (res.code == 200) {
  319. let odata = res.data
  320. //选择幼儿回显
  321. let studentArr = this.data.students
  322. let checkedStudents = []
  323. if (odata.participants.length > 0) {
  324. checkedStudents = odata.participants
  325. //判断两个数组是否有相同的id 如果有相同的id 给当前的student添加选中状态
  326. studentArr.forEach(item => {
  327. const isChecked = checkedStudents.some(citem => citem.studentId === item.studentId);
  328. item.checked = isChecked;
  329. });
  330. }
  331. let oarr2 = JSON.parse(JSON.stringify(checkedStudents))
  332. this.checkedStudentsHandle(oarr2)
  333. //观察背景回显
  334. let observeIndex = odata.scene.split(',')
  335. let observeSceneList = this.data.observeSceneList
  336. let observeParentIndex = 0
  337. let observeChildIndex = 0
  338. if (observeSceneList.length > 0) {
  339. for (let i in observeSceneList) {
  340. if (observeSceneList[i].expenseId == observeIndex[0]) {
  341. observeParentIndex = i
  342. break
  343. }
  344. }
  345. for (let i in observeSceneList[observeParentIndex].children) {
  346. if (observeSceneList[observeParentIndex].children[i].expenseId == observeIndex[1]) {
  347. observeChildIndex = i
  348. break
  349. }
  350. }
  351. }
  352. let scene = odata.recordDate + ',' + observeSceneList[observeParentIndex].expenseItem + observeSceneList[observeParentIndex].children[observeChildIndex].expenseItem + ',' + (odata.purpose ? odata.purpose : '')
  353. //观察背景回显-end
  354. //重组数据
  355. //type 1图片 3视频
  356. let oarr = odata.observationRecords.map(function (item) {
  357. //console.log(item)
  358. //由于后端返回的数据原因 导致得先把返回的数据剥离成两个数组 一个是语音部分的数组 一个是图片、视频的数组
  359. let paragraphsRecord = [] //存储语音
  360. let paragraphsIV = [] //存储图片视频
  361. let paragraphsIVLastArr = [] //存储图片视频过滤后的最终形态
  362. if (item.paragraphs && item.paragraphs.length > 0) {
  363. for (let i in item.paragraphs) {
  364. if (item.paragraphs[i].type == '2') {
  365. paragraphsRecord.push(item.paragraphs[i])
  366. paragraphsRecord.push(item.paragraphs[(i - 0) + 1])
  367. }
  368. }
  369. paragraphsIV = item.paragraphs.slice(paragraphsRecord.length) //通过语音部分数组的长度切割数组 后面的数组就都是图片或者视频的数组了
  370. for (let i in paragraphsIV) {
  371. paragraphsIVLastArr.push({
  372. url: paragraphsIV[i].content,
  373. type: paragraphsIV[i].type == '3' ? 'mp4' : paragraphsIV[i].type == '1' ? 'img' : '', //3是视频、1是图片
  374. })
  375. }
  376. }
  377. let oparagraphsRecord = []
  378. for (let i in paragraphsRecord) {
  379. if (paragraphsRecord[i].type == '2') {
  380. oparagraphsRecord.push({
  381. url: paragraphsRecord[i].content,
  382. txt: paragraphsRecord[(i - 0) + 1].content,
  383. time: that.timeHandle(paragraphsRecord[i].fileSize - 0),
  384. played: false,
  385. showTxt: false, //语音的文字部分是否展示
  386. showTip: false, //Tooltip 文字提示是否展示
  387. directionUp: false, //Tooltip的方向是向上还是向下
  388. })
  389. }
  390. }
  391. return {
  392. content: item.content,
  393. recordArr: oparagraphsRecord, //语音部分
  394. material: paragraphsIVLastArr, //图片、视频部分
  395. }
  396. })
  397. let str = ''
  398. let evaluationItems = odata.evaluationItems
  399. for (let i in evaluationItems) {
  400. str += (evaluationItems[i].sort + ':' + evaluationItems[i].syndrome)
  401. }
  402. str = str.substring(0, str.length - 1)
  403. this.setData({
  404. idx: odata.type,
  405. activityId: odata.activityId,
  406. activityMaterials: oarr,
  407. students: studentArr, //处理过的学生列表
  408. checkedStudents: checkedStudents, //选中的学生
  409. checkedStudentsTreated: checkedStudents, //选中的学生
  410. selectedDate: odata.recordDate, //记录日期
  411. observeParentIndex: observeParentIndex,
  412. childArray: this.data.observeSceneList[observeParentIndex].children, //ly-add 2023-09-15观察场景回显的问题
  413. observeChildIndex: observeChildIndex,
  414. observe: odata.purpose,
  415. observeStr: scene,
  416. observeNumber: odata.purpose ? odata.purpose.length : 0,
  417. areaStr: str,
  418. evaluationItems: odata.evaluationItems,
  419. measure: odata.measure,
  420. measureNumber: odata.measure ? odata.measure.length : 0,
  421. classCheckedId: odata.classId,
  422. pageNum: 1,
  423. activityList: [], //指向主题活动列表
  424. })
  425. if (odata.type == '2') {
  426. this.data.themeChecked.id = odata.activityId
  427. } else {
  428. this.data.themeChecked.id = ''
  429. this.setData({
  430. activityId: null
  431. })
  432. }
  433. //选择幼儿列表
  434. this.getStudent()
  435. this.getListSelectArea();
  436. this.getListSelectActivity();
  437. } else {
  438. wx.showToast({
  439. title: res.msg,
  440. icon: 'error',
  441. duration: 2000
  442. })
  443. }
  444. });
  445. },
  446. getObservationTypeListFun() {
  447. util.request(api.getObservationTypeList + this.data.userInfo.schoolId, '', 'get').then(res => {
  448. if (res.code == 200) {
  449. //获得列表数据 获取第一个idx的值
  450. this.setData({
  451. typeList: res.rows,
  452. idx: res.rows[0].id,
  453. sceneChecked: res.rows[0].scene
  454. })
  455. //观察场景请求数据
  456. this.getObserveScene();
  457. //选择幼儿列表
  458. this.getStudent()
  459. this.getListSelectArea();
  460. //指向主题活动
  461. this.setData({
  462. pageNum: 1,
  463. activityList: [], //指向主题活动列表
  464. flag: false,
  465. })
  466. this.getListSelectActivity(); //指向主题活动
  467. } else {
  468. wx.showModal({
  469. title: res.msg,
  470. icon: 'error',
  471. showCancel: false,
  472. duration: 3000
  473. });
  474. }
  475. });
  476. },
  477. selectClass() {
  478. util.request(api.selectClass + '?userId=' + this.data.userInfo.userId, '', 'get').then(res => {
  479. if (res.code == 200) {
  480. this.setData({
  481. classData: res.data,
  482. classCheckedId: res.data[0].classId
  483. })
  484. var oid = app.globalData.isRecordEdit ? app.globalData.recordId : '';
  485. if (!oid) {
  486. this.getObservationTypeListFun()
  487. }
  488. } else {
  489. wx.showModal({
  490. title: res.msg,
  491. icon: 'error',
  492. showCancel: false,
  493. duration: 3000
  494. });
  495. }
  496. });
  497. },
  498. openThemeHandle() {
  499. this.setData({
  500. openTheme: this.data.openTheme ? false : true
  501. })
  502. },
  503. cacelObserve() {
  504. const that = this
  505. wx.showModal({
  506. title: '',
  507. content: '是否清空当前页面数据',
  508. success(res) {
  509. if (res.confirm) {
  510. that.resetObserve()
  511. } else if (res.cancel) {
  512. //console.log('用户点击取消')
  513. }
  514. }
  515. })
  516. },
  517. //删除观察
  518. deleteObserve() {
  519. const that = this
  520. wx.showModal({
  521. title: '',
  522. content: '是否删除该观察记录',
  523. success(res) {
  524. if (res.confirm) {
  525. util.request(api.deleteObservation + that.data.oid, '', 'delete').then(res => {
  526. if (res.code == 200) {
  527. wx.showToast({
  528. title: '删除成功!',
  529. icon: 'success',
  530. duration: 2000
  531. })
  532. wx.switchTab({
  533. url: '/pages/report/report',
  534. });
  535. } else {
  536. wx.showModal({
  537. title: res.msg,
  538. icon: 'error',
  539. showCancel: false,
  540. duration: 3000
  541. });
  542. }
  543. });
  544. } else if (res.cancel) {
  545. //console.log('用户点击取消')
  546. }
  547. }
  548. })
  549. },
  550. save(e) {
  551. let ostatus = e.currentTarget.dataset.status
  552. if (this.data.checkedStudents.length == 0) {
  553. util.alert('请选择观察对象!')
  554. return
  555. }
  556. if (!this.data.selectedDate) {
  557. util.alert('请选择记录日期!')
  558. return
  559. }
  560. let allHasContent = true //后端要求内容必填 否则以下的内容都不会保存
  561. allHasContent = this.data.activityMaterials.every(function (item) {
  562. return item.content != '' && item.content != null && item.content != undefined
  563. })
  564. if (!allHasContent) {
  565. util.alert('请先输入内容!')
  566. return
  567. }
  568. //this.saveDocconfirm() //保存Ai续写的内容
  569. if (lock) return
  570. lock = true
  571. //处理过滤activityMaterials数据
  572. let actArr = this.data.activityMaterials.map(function (item) {
  573. let oarr = []
  574. //转换数据格式
  575. oarr[0] = {
  576. content: item.content
  577. }
  578. //录音部分转化成特定格式给后端
  579. for (let i in item.recordArr) {
  580. oarr.push({
  581. content: item.recordArr[i].url,
  582. fileSize: item.recordArr[i].time - 0, //后端要用这个字段名称存储时间
  583. })
  584. oarr.push({
  585. content: item.recordArr[i].txt
  586. })
  587. }
  588. //把图片、视频以content的子级的方式添加到paragraphs里面
  589. for (let i in item.material) {
  590. oarr.push({
  591. content: item.material[i].url
  592. })
  593. }
  594. return {
  595. paragraphs: oarr
  596. }
  597. })
  598. //console.log(actArr)
  599. for (let i in actArr) {
  600. //title等于编辑标题就代表没编辑过 paragraphs[0].content的值为空就代表textare没编辑过 paragraphs[1]不存在或者content为空就代表没编辑过
  601. if (!actArr[i].paragraphs[0].content && (!actArr[i].paragraphs[1] || !actArr[i].paragraphs[1].content)) {
  602. actArr.splice(i, 1)
  603. }
  604. }
  605. let observeSceneList = this.data.observeSceneList
  606. let observeParentIndex = this.data.observeParentIndex
  607. let observeChildIndex = this.data.observeChildIndex
  608. let scene = observeSceneList[observeParentIndex].expenseId + ',' + observeSceneList[observeParentIndex].children[observeChildIndex].expenseId
  609. //过滤数据成后台需要的结构
  610. let oevaluationItems = this.data.evaluationItems
  611. //console.log(oevaluationItems)
  612. oevaluationItems = oevaluationItems.map(function (item) {
  613. if (item.parentId) {
  614. return {
  615. evaluationIndicatorId: item.parentId,
  616. id: item.id
  617. }
  618. } else {
  619. return {
  620. evaluationIndicatorId: item.evaluationIndicatorId,
  621. id: item.id
  622. }
  623. }
  624. })
  625. let params = {
  626. userId: this.data.userInfo.userId,
  627. classId: this.data.classCheckedId,
  628. type: this.data.idx,
  629. activityId: this.data.themeChecked.id,
  630. recordDate: this.data.selectedDate,
  631. scene: scene,
  632. purpose: this.data.observe,
  633. measure: this.data.measure,
  634. observationParticipants: this.data.checkedStudents,
  635. observationRecords: actArr,
  636. evaluationItems: oevaluationItems,
  637. status: ostatus,
  638. }
  639. let requestStyle = ''
  640. let requestUrl = ''
  641. if (this.data.oid) {
  642. params.id = this.data.oid
  643. requestStyle = 'PUT'
  644. requestUrl = api.observationViewEdit
  645. } else {
  646. requestStyle = 'POST'
  647. requestUrl = api.observeSceneSave
  648. }
  649. wx.showLoading({
  650. title: '提交中'
  651. })
  652. util.request(requestUrl, params, requestStyle, 'application/json').then(res => {
  653. if (res.code == 200) {
  654. wx.showToast({
  655. title: '提交成功!',
  656. icon: 'success',
  657. duration: 2000
  658. })
  659. this.bookHandle('suc', '')
  660. } else {
  661. this.bookHandle('err', res)
  662. }
  663. });
  664. },
  665. bookHandle(result, ores) {
  666. const that = this
  667. let isSuccess = false
  668. wx.requestSubscribeMessage({
  669. tmplIds: ['hGQUXKwyQtenWhFPnKvGcZk1mq-hdjxOPSvh_5FT46w'],
  670. success(res) {
  671. if (result == 'suc') {
  672. isSuccess = true
  673. that.setData({
  674. oid: '',
  675. studentArr: [],
  676. activityId: null,
  677. checkedStudentsTreated: []
  678. })
  679. app.globalData.isActivityMaterials = false //阻止调用onshow
  680. wx.switchTab({
  681. url: '/pages/report/report',
  682. });
  683. lock = false
  684. wx.hideLoading();
  685. } else {
  686. wx.showToast({
  687. title: ores.msg,
  688. icon: 'error',
  689. duration: 2000
  690. })
  691. app.globalData.isActivityMaterials = false
  692. lock = false
  693. wx.hideLoading();
  694. }
  695. },
  696. complete() {
  697. //如果调用成功 则不用调用第二遍 complete是必调用的 所以拦住省得第二次触发
  698. if (isSuccess) return
  699. app.globalData.isActivityMaterials = false //阻止调用onshow
  700. wx.switchTab({
  701. url: '/pages/report/report',
  702. });
  703. lock = false
  704. wx.hideLoading();
  705. },
  706. })
  707. },
  708. saveHandle() {
  709. if (editType == 0) { //添加
  710. wx.switchTab({
  711. url: '/pages/activityn/activityn',
  712. })
  713. } else { //修改
  714. wx.navigateBack({
  715. delta: 1
  716. });
  717. }
  718. lock = false
  719. wx.hideLoading();
  720. },
  721. tabHandle(e) {
  722. //清掉幼儿发展水平评估的选中状态
  723. let oindex = e.currentTarget.dataset.idx
  724. this.setData({
  725. openArea: false,
  726. idx: oindex,
  727. areaStr: '', //重置幼儿发展水平评估选中的值
  728. areaSecondIndex: 0,
  729. areaFirstIndex: 0,
  730. // threeData: [],
  731. // selectArea: [],
  732. evaluationItems: [],
  733. sceneChecked: e.currentTarget.dataset.scene,
  734. themeExt: e.currentTarget.dataset.ext == 1 ? true : false,
  735. //classCheckedId: this.data.classData[0].classId,//ly-add 2023-10-09
  736. })
  737. // if(oindex == '2'){
  738. // this.setData({
  739. // pageNum: 1,
  740. // activityList: [],//指向主题活动列表
  741. // })
  742. // }
  743. this.getIndex();
  744. this.getListSelectArea();
  745. },
  746. monitorMeasureInput(e) {
  747. let value = e.detail.value.replace(/\n\s*/g, '\n'); // 获取输入的文本内容
  748. if (value.length > 500) {
  749. value = value.slice(0, 500);
  750. }
  751. this.setData({
  752. measure: value,
  753. measureNumber: value.length || 0,
  754. })
  755. },
  756. bindParentChange: function (e) {
  757. const observeParentIndex = e.detail.value;
  758. const childArray = this.data.observeSceneList[observeParentIndex].children; // 根据选中的父级索引获取对应的子集数组
  759. this.setData({
  760. observeParentIndex: observeParentIndex,
  761. childArray: childArray,
  762. observeChildIndex: 0,
  763. });
  764. },
  765. bindChildChange: function (e) {
  766. const observeChildIndex = e.detail.value;
  767. // 获取选中的父级和子集数据
  768. // const parentData = this.data.observeSceneList[this.data.parentIndex];
  769. // const childData = this.data.childArray[childIndex];
  770. this.setData({
  771. observeChildIndex: observeChildIndex
  772. });
  773. },
  774. //观察场景请求数据
  775. getObserveScene() {
  776. var that = this;
  777. util.request(api.listObserveScene, '', 'get').then(res => {
  778. if (res.code == 200) {
  779. that.setData({
  780. observeSceneList: res.data
  781. })
  782. this.getIndex()
  783. } else {
  784. wx.showToast({
  785. title: res.msg,
  786. icon: 'error',
  787. duration: 2000
  788. })
  789. }
  790. });
  791. },
  792. //获取观察场景的父级index、子集index
  793. getIndex() {
  794. const that = this
  795. let observeSceneList = this.data.observeSceneList
  796. observeSceneList.forEach(function (item, index) {
  797. //ly-edit 2023-09-15 非编辑状态添加默认的子级 如果是编辑状态就重新赋值
  798. let sceneChecked = that.data.sceneChecked
  799. if (item.expenseId == sceneChecked.split(",")[0]) {
  800. let cIndex = item.children.findIndex(citem => citem.expenseId == sceneChecked.split(",")[1]);
  801. that.setData({
  802. observeParentIndex: index,
  803. childArray: item.children, //先给一个默认值
  804. observeChildIndex: cIndex
  805. })
  806. }
  807. });
  808. },
  809. //选择记录日期
  810. bindDateChange(e) {
  811. let oval = e.detail.value
  812. this.setData({
  813. selectedDate: oval
  814. });
  815. },
  816. //指向主题活动加载更多
  817. loadMoreActivity() {
  818. if (this.data.flag) return
  819. this.getListSelectActivity();
  820. },
  821. //指向主题活动选中某一个元素
  822. checkActivityHandle(e) {
  823. let otheme = this.data.activityList
  824. let oidx = e.currentTarget.dataset.idx
  825. let obj = otheme[oidx]
  826. //重置选中状态
  827. otheme = otheme.map(item => {
  828. item.checked = false;
  829. return item;
  830. });
  831. otheme[oidx].checked = true
  832. let themeStr = otheme[oidx].name + (otheme[oidx].status == '1' ? '整理' : '计划') + (otheme[oidx].monthWeek ? otheme[oidx].monthWeek : '')
  833. this.setData({
  834. activityList: otheme,
  835. themeChecked: obj,
  836. openTheme: false,
  837. themeStr: themeStr,
  838. })
  839. },
  840. //加载指向主题活动数据
  841. getListSelectActivity() {
  842. let oclassId = this.data.classCheckedId == this.data.userInfo.schoolId ? '' : this.data.classCheckedId;
  843. var param = '&classId=' + oclassId + '&schoolId=' + this.data.userInfo.schoolId
  844. util.request(api.listSelectActivity + this.data.pageNum + '&pageSize=' + this.data.pageSize + param + '&id=' + (this.data.activityId ? this.data.activityId : '') + '&includeActiveAuthPlan=' + true, '', 'get').then(res => {
  845. if (res.code == 200) {
  846. let odata = res.rows
  847. let newDataList = this.data.activityList.concat(odata);
  848. //回显
  849. if (this.data.activityId) {
  850. for (let i in newDataList) {
  851. if (newDataList[i].id == this.data.activityId) {
  852. newDataList[i].checked = true
  853. let themeStr = newDataList[i].name + (newDataList[i].status == '1' ? '整理' : '计划') + newDataList[i].monthWeek
  854. this.setData({
  855. themeStr: themeStr
  856. })
  857. break
  858. }
  859. }
  860. }
  861. this.setData({
  862. activityList: newDataList,
  863. pageNum: this.data.pageNum + 1,
  864. })
  865. if (newDataList.length >= res.total) {
  866. this.setData({
  867. flag: true,
  868. moreTxt: '-无更多数据-'
  869. })
  870. } else {
  871. this.setData({
  872. flag: false,
  873. moreTxt: '-点击加载更多-'
  874. })
  875. }
  876. } else {
  877. wx.showModal({
  878. title: res.msg,
  879. icon: 'error',
  880. showCancel: false,
  881. duration: 3000
  882. });
  883. }
  884. });
  885. },
  886. //开关闭合 幼儿发展水平评估
  887. openAreaHandle() {
  888. //获取areaStr的值
  889. let str = ''
  890. let evaluationItems = this.data.evaluationItems
  891. for (let i in evaluationItems) {
  892. if (evaluationItems[i].label) {
  893. str += evaluationItems[i].label
  894. } else {
  895. str += (evaluationItems[i].sort + ':' + evaluationItems[i].syndrome)
  896. }
  897. }
  898. str = str.substring(0, str.length - 1)
  899. this.setData({
  900. openArea: this.data.openArea ? false : true,
  901. areaStr: str
  902. })
  903. },
  904. checkedAreaHandle(e) {
  905. let parentIndex = e.currentTarget.dataset.parentindex
  906. let childindex = e.currentTarget.dataset.childindex
  907. let oitem = e.currentTarget.dataset.item
  908. let evaluationItems = this.data.evaluationItems
  909. let threeData = this.data.threeData
  910. //思路:点击的时候 判断当前checked是否为true 如果是true则改为false 如果是false通过父级index 把父级下标下所有的checked改为false 在子级下标对应的那个值改为true
  911. //1、判断点击的元素 checked是否为true
  912. let activeList = ''
  913. if (this.data.showAreaSecond) {
  914. activeList = threeData.children[parentIndex].children[childindex] //选中的元素
  915. } else {
  916. activeList = threeData[parentIndex].children[childindex] //选中的元素
  917. }
  918. if (activeList.checked) { //重置 如果是true改为false
  919. for (let i in evaluationItems) { //删除相同id的item
  920. if (evaluationItems[i].id == oitem.id) {
  921. evaluationItems.splice(i, 1)
  922. break
  923. }
  924. }
  925. activeList.checked = false
  926. } else {
  927. if (this.data.showAreaSecond) {
  928. threeData.children[parentIndex].children.forEach(function (item) {
  929. //遍历清除该点击元素同级的所有元素
  930. for (let i in evaluationItems) {
  931. if (item.id == evaluationItems[i].id) {
  932. evaluationItems.splice(i, 1)
  933. }
  934. }
  935. item.checked = false
  936. })
  937. } else {
  938. threeData[parentIndex].children.forEach(function (item) {
  939. //遍历清除该点击元素同级的所有元素
  940. for (let i in evaluationItems) {
  941. if (item.id == evaluationItems[i].id) {
  942. evaluationItems.splice(i, 1)
  943. }
  944. }
  945. item.checked = false
  946. })
  947. }
  948. evaluationItems.push(oitem)
  949. activeList.checked = true
  950. }
  951. //如果threeData里有checked是true 那就出现角标
  952. //获取第一级的index
  953. //console.log(this.data.areaFirstIndex)
  954. //console.log(threeData)
  955. let hasCornerMark = false
  956. if (this.data.showAreaSecond) {
  957. hasCornerMark = this.findCheckedItem(threeData.children)
  958. } else {
  959. hasCornerMark = this.findCheckedItem(threeData)
  960. }
  961. let selectArea = this.data.selectArea
  962. selectArea[this.data.areaFirstIndex].checked = hasCornerMark
  963. //console.log(evaluationItems)
  964. this.setData({
  965. threeData,
  966. selectArea
  967. })
  968. },
  969. //查找多层级数组中是否带有checked为true的属性并返回
  970. findCheckedItem(arr) {
  971. const that = this
  972. for (let item of arr) {
  973. if (item.checked === true) {
  974. return true;
  975. }
  976. if (item.children && item.children.length > 0) {
  977. const found = that.findCheckedItem(item.children);
  978. if (found) {
  979. return true;
  980. }
  981. }
  982. }
  983. return false;
  984. },
  985. updateCheckedStatus(arr1, arr2) {
  986. for (let i = 0; i < arr1.length; i++) {
  987. // 检查当前元素的id是否在arr2中存在
  988. if (arr2.some(item => item.id === arr1[i].id)) {
  989. arr1[i].checked = true;
  990. }
  991. // 递归遍历children数组
  992. if (arr1[i].children) {
  993. this.updateCheckedStatus(arr1[i].children, arr2);
  994. }
  995. }
  996. },
  997. //第三级页面显示
  998. getThreeData() {
  999. let listSelect = this.data.listSelect
  1000. if (this.data.showAreaSecond) {
  1001. //需要加children
  1002. let areaSecondIndex = this.data.areaSecondIndex
  1003. //回显
  1004. if(listSelect.length > 0 && this.data.evaluationItems.length > 0){
  1005. this.updateCheckedStatus(listSelect[areaSecondIndex].children, this.data.evaluationItems)
  1006. }
  1007. this.setData({
  1008. threeData: listSelect[areaSecondIndex]
  1009. })
  1010. } else {
  1011. //不需要加children
  1012. //回显
  1013. if(listSelect.length > 0 && this.data.evaluationItems.length > 0){
  1014. this.updateCheckedStatus(listSelect, this.data.evaluationItems)
  1015. }
  1016. this.setData({
  1017. threeData: listSelect
  1018. })
  1019. }
  1020. },
  1021. getAreaSecondIndex(e) {
  1022. let index = e.currentTarget.dataset.index
  1023. this.setData({
  1024. areaSecondIndex: index
  1025. })
  1026. this.getThreeData()
  1027. },
  1028. //指标列表
  1029. getlistSelect(id) {
  1030. util.request(api.listSelect + id + '&observationViewId=' + this.data.observationViewId, '', 'get').then(res => {
  1031. if (res.code == 200) {
  1032. //有可能消失的第二级 如果第一级的id用于查询指标列表 指标列表type是3 则第二级显示 如果type是4则该第二级隐藏 ***如果没有children 直接使用选项卡*** 第二级是单选
  1033. let odata = res.data
  1034. let showAreaSecond = this.data.showAreaSecond //是否展示二级
  1035. // 使用find方法找到第一个包含非null children数组的元素
  1036. const elementWithChildren = odata.find(element => element.children !== null);
  1037. let firstType = ''
  1038. // 如果找到了包含非null children数组的元素
  1039. if (elementWithChildren) {
  1040. // 使用some方法遍历children数组,找到第一个type字段的值
  1041. firstType = elementWithChildren.children.find(child => child.type).type;
  1042. } else {
  1043. //都没有children的情况
  1044. //console.log('No element with non-null children found.');
  1045. }
  1046. if (odata.length > 0 && (firstType == '3')) {
  1047. showAreaSecond = true
  1048. } else {
  1049. showAreaSecond = false
  1050. }
  1051. this.setData({
  1052. listSelect: res.data,
  1053. showAreaSecond: showAreaSecond
  1054. })
  1055. //获取并展示第三级页面的值
  1056. this.getThreeData()
  1057. } else {
  1058. wx.showModal({
  1059. title: res.msg,
  1060. icon: 'error',
  1061. showCancel: false,
  1062. duration: 3000
  1063. });
  1064. }
  1065. });
  1066. },
  1067. //一级的tab操作
  1068. getSelectAreaId(e) {
  1069. let id = e.currentTarget.dataset.id
  1070. let index = e.currentTarget.dataset.index
  1071. this.setData({
  1072. areaFirstIndex: index,
  1073. })
  1074. this.getlistSelect(id)
  1075. },
  1076. //选择评估对象
  1077. getListSelectArea() {
  1078. util.request(api.listSelectArea2 + (this.data.userInfo.schoolId ? this.data.userInfo.schoolId : '') + '/' + this.data.idx, '', 'get').then(res => {
  1079. if (res.code == 200) {
  1080. let odata = res.data
  1081. let arryNew = []
  1082. odata.map((item) => {
  1083. arryNew.push(Object.assign({}, item, {
  1084. checked: false
  1085. }))
  1086. })
  1087. this.setData({
  1088. selectArea: arryNew
  1089. })
  1090. if (odata.length == 0) return
  1091. //默认查询第一条id对应的指标列表
  1092. this.getlistSelect(odata[0].id)
  1093. } else {
  1094. wx.showModal({
  1095. title: res.msg,
  1096. icon: 'error',
  1097. showCancel: false,
  1098. duration: 3000
  1099. });
  1100. }
  1101. });
  1102. },
  1103. monitorObserveInput(e) {
  1104. this.setData({
  1105. observe: e.detail.value,
  1106. observeNumber: e.detail.cursor
  1107. })
  1108. },
  1109. openObserveHandle() {
  1110. let selectedDate = this.data.selectedDate
  1111. let observeSceneList = this.data.observeSceneList
  1112. let observeParentIndex = this.data.observeParentIndex
  1113. let observeChildIndex = this.data.observeChildIndex
  1114. let scene = selectedDate + ',' + observeSceneList[observeParentIndex].expenseItem + observeSceneList[observeParentIndex].children[observeChildIndex].expenseItem + ',' + (this.data.observe ? this.data.observe : '')
  1115. this.setData({
  1116. openObserve: this.data.openObserve ? false : true,
  1117. observeStr: scene
  1118. })
  1119. },
  1120. //处理选中学生如果超过十个用...显示
  1121. checkedStudentsHandle(oarr) {
  1122. if (this.data.openStudents && oarr.length > 10) {
  1123. //如果关闭的时候 选中的列表超过10个则截取列表剩下9个显示
  1124. oarr = oarr.slice(0, 9)
  1125. this.setData({
  1126. checkedStudentsTreated: oarr
  1127. })
  1128. } else {
  1129. this.setData({
  1130. checkedStudentsTreated: this.data.checkedStudents
  1131. })
  1132. }
  1133. },
  1134. openStudentHandle() {
  1135. let oarr = JSON.parse(JSON.stringify(this.data.checkedStudents))
  1136. this.checkedStudentsHandle(oarr)
  1137. this.setData({
  1138. openStudents: this.data.openStudents ? false : true
  1139. })
  1140. },
  1141. checkHandle(e) {
  1142. let idx = e.currentTarget.dataset.idx
  1143. let arr = this.data.students
  1144. arr[idx].checked = arr[idx].checked == true ? false : true
  1145. let checkedarr = arr.filter(function (item) {
  1146. return item.checked == true
  1147. })
  1148. this.setData({
  1149. students: arr,
  1150. checkedStudents: checkedarr
  1151. })
  1152. },
  1153. checkClassHandle(e) {
  1154. //this.data.classCheckedId == e.currentTarget.datasetid ? [] : this.data.checkedStudentsTreated
  1155. this.setData({
  1156. classCheckedId: e.currentTarget.dataset.id,
  1157. flag: false,
  1158. pageNum: 1,
  1159. activityList: [], //指向主题活动列表
  1160. students: [],
  1161. checkedStudents: [],
  1162. checkedStudentsTreated: [],
  1163. themeChecked: {},
  1164. themeStr: '',
  1165. activityId: null
  1166. })
  1167. this.getStudent()
  1168. this.getListSelectActivity();//ly-edit 2023-10-09
  1169. this.getListSelectArea(); //ly-add 2023-10-09
  1170. },
  1171. getStudent() {
  1172. var param = {};
  1173. param.deptId = this.data.classCheckedId;
  1174. param.schoolId = wx.getStorageSync('userInfo').schoolId;
  1175. util.request(api.studentList, param, 'POST').then(res => {
  1176. if (res.code == 200) {
  1177. let oarr = res.rows.map(function (item) {
  1178. return {
  1179. studentId: item.id,
  1180. studentName: item.name,
  1181. studentNumber: item.number,
  1182. studentImage: item.headUrl ? item.headUrl : '',
  1183. sex: item.sex,
  1184. checked: false
  1185. }
  1186. })
  1187. if (this.data.checkedStudents.length > 0) {
  1188. let checkedStudents = this.data.checkedStudents
  1189. //判断两个数组是否有相同的id 如果有相同的id 给当前的student添加选中状态
  1190. oarr.forEach(item => {
  1191. const isChecked = checkedStudents.some(citem => citem.studentId === item.studentId);
  1192. item.checked = isChecked;
  1193. });
  1194. }
  1195. this.setData({
  1196. students: oarr
  1197. })
  1198. } else {
  1199. wx.showModal({
  1200. title: res.msg,
  1201. icon: 'error',
  1202. showCancel: false,
  1203. duration: 3000
  1204. });
  1205. }
  1206. });
  1207. },
  1208. timeHandle(time) {
  1209. if (time < 10) {
  1210. return '0' + time
  1211. } else {
  1212. return time
  1213. }
  1214. },
  1215. //重置录音按钮状态
  1216. resetRecordState() {
  1217. let activityMaterials = this.data.activityMaterials
  1218. activityMaterials[this.data.parentIndex].recordState = false
  1219. this.setData({
  1220. activityMaterials: activityMaterials
  1221. })
  1222. },
  1223. addListHandle() {
  1224. let obj = this.data.activityMaterials
  1225. obj.push({
  1226. content: '',
  1227. material: []
  1228. })
  1229. this.setData({
  1230. activityMaterials: obj
  1231. })
  1232. },
  1233. textareaBlurHandle(e) {
  1234. let oval = e.detail.value
  1235. let obj = this.data.activityMaterials
  1236. let idx = e.currentTarget.dataset.idx
  1237. obj[idx].content = oval
  1238. this.setData({
  1239. activityMaterials: obj
  1240. })
  1241. },
  1242. preview(e) {
  1243. let currentUrl = e.currentTarget.dataset.src
  1244. let pidx = e.currentTarget.dataset.pidx //父级循环的index
  1245. const oarr = []
  1246. for (let i in this.data.activityMaterials[pidx].material) {
  1247. oarr.push(this.data.activityMaterials[pidx].material[i].url)
  1248. }
  1249. wx.previewImage({
  1250. current: currentUrl, // 当前显示图片的http链接
  1251. urls: oarr // 需要预览的图片http链接列表
  1252. })
  1253. },
  1254. closeHadle(e) {
  1255. const that = this
  1256. wx.showModal({
  1257. title: '',
  1258. content: '是否删除素材',
  1259. success(res) {
  1260. if (res.confirm) {
  1261. let obj = that.data.activityMaterials
  1262. let pidx = e.currentTarget.dataset.pidx //父级循环的index
  1263. let idx = e.currentTarget.dataset.idx //子级循环的index
  1264. obj[pidx].material.splice(idx, 1)
  1265. that.setData({
  1266. activityMaterials: obj
  1267. })
  1268. } else if (res.cancel) {
  1269. //console.log('用户点击取消')
  1270. }
  1271. }
  1272. })
  1273. },
  1274. //上传图片、视频
  1275. uploadFile: function (e) {
  1276. //如果不添加这个判断 则在这里会默认调用onshow
  1277. app.globalData.isActivityMaterials = true //阻止调用onshow
  1278. const that = this
  1279. let obj = this.data.activityMaterials
  1280. let pidx = e.currentTarget.dataset.idx
  1281. wx.chooseMedia({
  1282. count: 9, // 设置为需要上传的文件数量
  1283. mediaType: ['image', 'video'],
  1284. sizeType: ['compressed'], //压缩图片
  1285. success: function (res) {
  1286. const files = res.tempFiles;
  1287. // 遍历选择的文件数组,依次上传每个文件
  1288. wx.showLoading({
  1289. title: '上传中'
  1290. })
  1291. files.forEach(function (file) {
  1292. const tempFilePath = file.tempFilePath;
  1293. wx.uploadFile({
  1294. url: BASE_URL + 'common/uploadMediaToTencent',
  1295. formData: {
  1296. 'userId': wx.getStorageSync('userInfo').userId,
  1297. 'scene': 'observation'
  1298. },
  1299. filePath: tempFilePath,
  1300. name: 'file',
  1301. success: function (res) {
  1302. let ores = JSON.parse(res.data)
  1303. //每个数组里添加一个type值是mp4或者img,在for循环里通过type赋值到mp4或者img里面
  1304. let otype = that.getFileExtension(ores.url)
  1305. if (otype) {
  1306. let params = {
  1307. url: ores.url,
  1308. type: otype
  1309. }
  1310. obj[pidx].material.push(params)
  1311. }
  1312. that.setData({
  1313. activityMaterials: obj,
  1314. })
  1315. wx.hideLoading();
  1316. },
  1317. fail: function (res) {
  1318. // 处理上传失败后的逻辑
  1319. wx.hideLoading();
  1320. }
  1321. })
  1322. });
  1323. }
  1324. })
  1325. },
  1326. //用一个方法来判断 返回的文件是mp4 还是图片
  1327. getFileExtension(url) {
  1328. const dotIndex = url.lastIndexOf('.');
  1329. const extension = url.substring(dotIndex + 1);
  1330. if (/(jpg|jpeg|png)$/.test(extension.toLowerCase())) {
  1331. return 'img'
  1332. } else if (/(mp4|avi|mov)$/.test(extension.toLowerCase())) {
  1333. return 'mp4'
  1334. }
  1335. return false
  1336. },
  1337. deleteHandle(e) {
  1338. const that = this
  1339. wx.showModal({
  1340. title: '',
  1341. content: '是否删除',
  1342. success(res) {
  1343. if (res.confirm) {
  1344. let obj = that.data.activityMaterials
  1345. let idx = e.currentTarget.dataset.idx //子级循环的index
  1346. obj.splice(idx, 1)
  1347. that.setData({
  1348. activityMaterials: obj
  1349. })
  1350. } else if (res.cancel) {
  1351. //console.log('用户点击取消')
  1352. }
  1353. }
  1354. })
  1355. },
  1356. //识别语音 -- 初始化
  1357. initRecord: function () {
  1358. var that = this;
  1359. wx.onSocketOpen((res) => { // websocket打开
  1360. //console.log('监听到 WebSocket 连接已打开' + res);
  1361. })
  1362. wx.onSocketError((err) => { //连接失败
  1363. //console.log('websocket连接失败', err);
  1364. wx.showToast({
  1365. title: 'websocket连接失败',
  1366. icon: 'none',
  1367. duration: 2000,
  1368. mask: false
  1369. })
  1370. })
  1371. wx.onSocketMessage((res) => { //接收返回值
  1372. var data = JSON.parse(res.data)
  1373. //console.log(data)
  1374. if (data.code != 0) {
  1375. //console.log("error code " + data.code + ", reason " + data.message)
  1376. return
  1377. }
  1378. let str = ""
  1379. if (data.data.status == 2) { //最终识别结果
  1380. // data.data.status ==2 说明数据全部返回完毕,可以关闭连接,释放资源
  1381. wxst.close();
  1382. } else { //中间识别结果
  1383. }
  1384. iatResult[data.data.result.sn] = data.data.result
  1385. if (data.data.result.pgs == 'rpl') {
  1386. data.data.result.rg.forEach(i => {
  1387. iatResult[i] = null
  1388. })
  1389. }
  1390. iatResult.forEach(i => {
  1391. if (i != null) {
  1392. i.ws.forEach(j => {
  1393. j.cw.forEach(k => {
  1394. str += k.w
  1395. })
  1396. })
  1397. }
  1398. });
  1399. // console.log('这个是中间的语音识别结果')
  1400. // console.log(str)
  1401. that.setData({
  1402. contentTxt: str //这个是中间的语音识别结果
  1403. })
  1404. if (!this.data.contentTxt) {
  1405. wx.showToast({
  1406. title: '识别失败,请重新录入',
  1407. icon: 'none',
  1408. duration: 2000,
  1409. mask: false
  1410. })
  1411. return
  1412. }
  1413. })
  1414. wx.onSocketClose((res) => { //WebSocket连接已关闭!
  1415. //var that = this;
  1416. recorderManager.stop();
  1417. // var str = that.data.contentTxt;
  1418. // console.log(str);
  1419. // str = str.replace(/\s*/g, "");//去除空格
  1420. // if (str.substr(str.length - 1, 1) == "。") {//去除句号
  1421. // str = str.substr(0, str.length - 1);
  1422. // }
  1423. // console.log('这个是最后确定的语音识别结果', str)
  1424. // that.setData({
  1425. // contentTxt: str//这个是最后确定的语音识别结果
  1426. // })
  1427. //console.log('WebSocket连接已关闭!')
  1428. })
  1429. },
  1430. //录音和停止录音操作
  1431. recordHandle(e) {
  1432. let oactivityMaterials = this.data.activityMaterials
  1433. let parentIndex = e.currentTarget.dataset.idx
  1434. this.setData({ //获取父级的下标 后面录音结束后给对应的模块赋值
  1435. parentIndex: parentIndex
  1436. })
  1437. //改成点击事件
  1438. if (!oactivityMaterials[parentIndex].recordState) {
  1439. wx.showToast({
  1440. title: '开始录音',
  1441. icon: 'none',
  1442. duration: 1000
  1443. })
  1444. //兄弟节点的录音按钮改成灰色
  1445. if (oactivityMaterials.length > 1) {
  1446. for (let i in oactivityMaterials) {
  1447. oactivityMaterials[i].recordState = false
  1448. }
  1449. this.setData({
  1450. activityMaterials: oactivityMaterials
  1451. })
  1452. }
  1453. oactivityMaterials[parentIndex].recordState = true
  1454. this.setData({
  1455. activityMaterials: oactivityMaterials //录音状态
  1456. })
  1457. wx.getSetting({ //查看用户有没有开启语音权限
  1458. success(res) {
  1459. if (res.authSetting['scope.record']) {
  1460. wx.authorize({
  1461. scope: 'scope.record',
  1462. success() {
  1463. var xfurl = "";
  1464. wx.request({ //请求接口 获取讯飞语音鉴权
  1465. url: BASE_URL + 'assistant/url',
  1466. method: "get",
  1467. header: {
  1468. 'content-type': 'application/json' // 默认值
  1469. },
  1470. success: function (res) {
  1471. //console.log('鉴权结果start:');
  1472. //console.log(res);
  1473. if (res.statusCode == "200" && res.data) {
  1474. xfurl = res.data;
  1475. wxst = wx.connectSocket({ // 开启websocket连接
  1476. url: xfurl,
  1477. method: 'GET',
  1478. success: function (res) {
  1479. recorderManager.start(searchoptions); //开始录音
  1480. }
  1481. });
  1482. } else {
  1483. wx.showToast({
  1484. title: '获取语音鉴权失败',
  1485. icon: 'none',
  1486. mask: true,
  1487. duration: 3000
  1488. })
  1489. }
  1490. },
  1491. fail: function () {
  1492. wx.showToast({
  1493. title: '获取语音鉴权失败',
  1494. icon: 'none',
  1495. mask: true,
  1496. duration: 3000
  1497. })
  1498. }
  1499. })
  1500. },
  1501. fail() {
  1502. wx.showModal({
  1503. title: '微信授权',
  1504. content: '您当前未开启语音权限,请在右上角设置(···)中开启“录音功能”',
  1505. showCancel: false,
  1506. success(res) {
  1507. if (res.confirm) {
  1508. //console.log('用户点击确定')
  1509. }
  1510. }
  1511. })
  1512. }
  1513. })
  1514. } else {
  1515. wx.showModal({
  1516. title: '微信授权',
  1517. content: '您当前未开启语音权限,请在右上角设置(···)中开启“录音功能”',
  1518. showCancel: false,
  1519. success(res) {
  1520. if (res.confirm) {
  1521. //console.log('用户点击确定')
  1522. }
  1523. }
  1524. })
  1525. }
  1526. }
  1527. })
  1528. } else {
  1529. oactivityMaterials[parentIndex].recordState = false
  1530. this.setData({
  1531. activityMaterials: oactivityMaterials
  1532. })
  1533. recorderManager.stop();
  1534. }
  1535. },
  1536. //播放操作
  1537. playHandle(e) {
  1538. const that = this
  1539. let idx = e.currentTarget.dataset.idx
  1540. let pidx = e.currentTarget.dataset.pidx
  1541. //recordArr的字段有url/txt/time/played/showTxt: false,//语音的文字部分是否展示showTip: false,//Tooltip 文字提示是否展示directionUp: false,//Tooltip的方向是向上还是向下
  1542. let activityMaterials = this.data.activityMaterials
  1543. let orecordArr = activityMaterials[pidx].recordArr[idx]
  1544. innerAudioContext.src = orecordArr.url
  1545. if (!orecordArr.played) {
  1546. //查找兄弟节点 把所有的played状态改成false
  1547. for (let i in activityMaterials) {
  1548. for (let j in activityMaterials[i].recordArr) {
  1549. activityMaterials[i].recordArr[j].played = false
  1550. }
  1551. }
  1552. // if(activityMaterials && activityMaterials.length > 1){
  1553. // that.setData({
  1554. // activityMaterials: activityMaterials
  1555. // })
  1556. // }
  1557. //播放
  1558. orecordArr.played = true
  1559. innerAudioContext.play() // 播放
  1560. innerAudioContext.onEnded(() => {
  1561. //console.log('语音播放结束');
  1562. orecordArr.played = false
  1563. that.setData({
  1564. activityMaterials: activityMaterials
  1565. })
  1566. });
  1567. } else {
  1568. //关闭
  1569. orecordArr.played = false
  1570. innerAudioContext.stop() // 停止
  1571. }
  1572. this.setData({
  1573. activityMaterials: activityMaterials
  1574. })
  1575. },
  1576. onLongPress(e) {
  1577. //console.log(e)
  1578. //const listItem = e.currentTarget;
  1579. let activityMaterials = this.data.activityMaterials
  1580. let pidx = e.currentTarget.dataset.pidx //父级下标
  1581. let idx = e.currentTarget.dataset.idx //子级下标
  1582. //console.log(e.touches[0].clientY)
  1583. let oClientY = e.touches[0].clientY * 2 //点击的位置和Y轴顶部的距离
  1584. //隐藏所有语音列表的tip
  1585. //console.log(activityMaterials)
  1586. for (let i in activityMaterials) {
  1587. for (let j in activityMaterials[i].recordArr) {
  1588. activityMaterials[i].recordArr[j].showTip = false
  1589. }
  1590. }
  1591. this.setData({
  1592. activityMaterials: activityMaterials
  1593. })
  1594. //判断只要距离Y轴顶部的距离 大于220rpx 一律往上面冒泡
  1595. if (oClientY > 220) {
  1596. activityMaterials[pidx].recordArr[idx].directionUp = true
  1597. } else {
  1598. activityMaterials[pidx].recordArr[idx].directionUp = false
  1599. }
  1600. activityMaterials[pidx].recordArr[idx].showTip = true
  1601. this.setData({
  1602. activityMaterials: activityMaterials,
  1603. maskShow: true
  1604. })
  1605. },
  1606. txtRecordHandle(e) {
  1607. let activityMaterials = this.data.activityMaterials
  1608. let pidx = e.currentTarget.dataset.pidx //父级下标
  1609. let idx = e.currentTarget.dataset.idx //子级下标
  1610. activityMaterials[pidx].recordArr[idx].showTxt = true
  1611. activityMaterials[pidx].recordArr[idx].showTip = false
  1612. this.setData({
  1613. activityMaterials: activityMaterials
  1614. })
  1615. },
  1616. delRecordHandle(e) {
  1617. let activityMaterials = this.data.activityMaterials
  1618. let pidx = e.currentTarget.dataset.pidx //父级下标
  1619. let idx = e.currentTarget.dataset.idx //子级下标
  1620. activityMaterials[pidx].recordArr.splice(idx, 1)
  1621. this.setData({
  1622. activityMaterials: activityMaterials,
  1623. maskShow: false
  1624. })
  1625. },
  1626. closeTipHandle() {
  1627. let activityMaterials = this.data.activityMaterials
  1628. //隐藏所有语音列表的tip
  1629. //console.log(activityMaterials)
  1630. for (let i in activityMaterials) {
  1631. for (let j in activityMaterials[i].recordArr) {
  1632. activityMaterials[i].recordArr[j].showTip = false
  1633. }
  1634. }
  1635. this.setData({
  1636. activityMaterials: activityMaterials,
  1637. maskShow: false
  1638. })
  1639. },
  1640. onUnload: function () {
  1641. innerAudioContext.stop() // 停止
  1642. },
  1643. onShareAppMessage() {},
  1644. recordAiHandle(e) {
  1645. let oactivityMaterials = this.data.activityMaterials
  1646. let parentIndex = e ? e.currentTarget.dataset.idx : this.data.aiParentIndex
  1647. let params = {
  1648. docstyle: 3, //如果观察记录有值输入3 没值输入1
  1649. content: {
  1650. 'level1': this.data.observeSceneList[this.data.observeParentIndex].expenseItem,
  1651. 'level2': this.data.childArray[this.data.observeChildIndex].expenseItem,
  1652. },
  1653. text: oactivityMaterials[parentIndex].content
  1654. }
  1655. wx.showLoading({
  1656. title: '加载中...'
  1657. });
  1658. util.request('https://ai.keeko.ai/docgeneration', params, 'POST', 'application/json').then(res => {
  1659. wx.hideLoading();
  1660. if (res.result == 1) {
  1661. this.setData({
  1662. aiPolish: res.data.text,
  1663. aistyle: e ? e.currentTarget.dataset.aistyle : this.data.aistyle,
  1664. aiParentIndex: parentIndex
  1665. })
  1666. if (!this.data.showPolish) {
  1667. this.setData({
  1668. showPolish: true
  1669. })
  1670. }
  1671. } else {
  1672. wx.showToast({
  1673. title: '尚在学习中',
  1674. icon: 'none',
  1675. mask: true,
  1676. duration: 3000
  1677. })
  1678. }
  1679. });
  1680. },
  1681. //Ai续写 观察目的
  1682. aimAiHandle(e) {
  1683. let observe = this.data.observe
  1684. let params = {
  1685. docstyle: !observe ? 1 : 2, //如果目的有值输入2 没值输入1
  1686. content: {
  1687. 'level1': this.data.observeSceneList[this.data.observeParentIndex].expenseItem,
  1688. 'level2': this.data.childArray[this.data.observeChildIndex].expenseItem,
  1689. },
  1690. text: observe
  1691. }
  1692. wx.showLoading({
  1693. title: '加载中...'
  1694. });
  1695. util.request('https://ai.keeko.ai/docgeneration', params, 'POST', 'application/json').then(res => {
  1696. wx.hideLoading();
  1697. if (res.result == 1) {
  1698. this.setData({
  1699. aiPolish: res.data.text,
  1700. aistyle: e ? e.currentTarget.dataset.aistyle : this.data.aistyle
  1701. })
  1702. //aiAgain 重写的时候不刷新弹窗状态
  1703. if (!this.data.showPolish) {
  1704. this.setData({
  1705. showPolish: true
  1706. })
  1707. }
  1708. } else {
  1709. wx.showToast({
  1710. title: '尚在学习中',
  1711. icon: 'none',
  1712. mask: true,
  1713. duration: 3000
  1714. })
  1715. }
  1716. });
  1717. },
  1718. //判断是不是空对象
  1719. isEmptyObject(obj) {
  1720. return Object.keys(obj).length === 0;
  1721. },
  1722. saveDocconfirm() {
  1723. let observe = this.data.observe
  1724. let level1 = this.data.observeSceneList[this.data.observeParentIndex].expenseItem
  1725. let level2 = this.data.childArray[this.data.observeChildIndex].expenseItem
  1726. let observeParams = {}
  1727. if (observe) {
  1728. observeParams = {
  1729. docstyle: 2, //2代表观察目的
  1730. content: {
  1731. 'level1': level1,
  1732. 'level2': level2,
  1733. },
  1734. title: '观察目的',
  1735. text: this.data.aimAiKeyword,
  1736. doctext: this.data.aimAiPolish
  1737. }
  1738. //console.log(observeParams)
  1739. }
  1740. //先过滤无值的项
  1741. let activityArr = []
  1742. if (this.data.activityMaterials.length > 0 && this.data.activityMaterials[0].content) {
  1743. activityArr = this.data.activityMaterials.map(function (item) {
  1744. if (item.recordAiPolish) {
  1745. return {
  1746. docstyle: 3, //2代表观察目的
  1747. content: {
  1748. 'level1': level1,
  1749. 'level2': level2,
  1750. },
  1751. title: '观察记录',
  1752. text: item.aiKeyword,
  1753. doctext: item.recordAiPolish
  1754. }
  1755. }
  1756. })
  1757. }
  1758. if (!this.isEmptyObject(observeParams)) {
  1759. activityArr.unshift(observeParams)
  1760. }
  1761. let params = {
  1762. doc: activityArr
  1763. }
  1764. if (activityArr.length == 0) return
  1765. util.request('https://ai.keeko.ai/docconfirm', params, 'POST', 'application/json').then(res => {
  1766. //console.log(res)
  1767. });
  1768. },
  1769. aiCancel() {
  1770. this.setData({
  1771. showPolish: false,
  1772. })
  1773. },
  1774. aiAgain() {
  1775. if (this.data.aistyle == '1') {
  1776. this.aimAiHandle()
  1777. } else {
  1778. this.recordAiHandle()
  1779. }
  1780. },
  1781. aiConfirm() {
  1782. if (this.data.aistyle == '1') {
  1783. let otxt = this.data.aiPolish
  1784. let value = (this.data.observe + otxt).replace(/\n\s*/g, '\n'); // 获取输入的文本内容
  1785. if (value.length > 500) {
  1786. value = value.slice(0, 500);
  1787. }
  1788. this.setData({
  1789. aimAiPolish: otxt,
  1790. aimAiKeyword: this.data.observe, //关键词
  1791. observe: value,
  1792. observeNumber: value.length,
  1793. showPolish: false,
  1794. })
  1795. } else {
  1796. let oactivityMaterials = this.data.activityMaterials
  1797. let parentIndex = this.data.aiParentIndex
  1798. let otxt = this.data.aiPolish
  1799. let value = (oactivityMaterials[parentIndex].content + otxt).replace(/\n\s*/g, '\n'); // 获取输入的文本内容
  1800. if (value.length > 500) {
  1801. value = value.slice(0, 500);
  1802. }
  1803. oactivityMaterials[parentIndex].aiKeyword = oactivityMaterials[parentIndex].content
  1804. oactivityMaterials[parentIndex].content = value
  1805. oactivityMaterials[parentIndex].recordAiPolish = otxt
  1806. this.setData({
  1807. activityMaterials: oactivityMaterials,
  1808. showPolish: false,
  1809. })
  1810. }
  1811. },
  1812. monitorPopInput(e) {
  1813. this.setData({
  1814. aiPolish: e.detail.value
  1815. })
  1816. },
  1817. })
  1. .wrap{ padding: 30rpx 30rpx 100rpx 30rpx;}
  2. .header-tab{ display: flex; overflow-x: scroll;}
  3. .tab-list{ position: relative; margin-right: 20rpx; padding: 0; background: #fff; text-align: center;border-radius: 16rpx; opacity: 0.3;}
  4. .tab-list:last-child{ margin-right: 0;}
  5. .icon-daily{ margin: 0 auto; display: block; width: 225rpx; height: 178rpx; border-radius: 10rpx;}
  6. .tab-list .v1{ position: absolute; bottom: 0; left: 0; width: 100%; height: 50rpx; line-height: 50rpx; background: #33a9ff; color: #fff; font-size: 28rpx; border-radius: 0 0 10rpx 10rpx; white-space: nowrap; text-overflow: ellipsis; overflow: hidden;}
  7. .tab-list.active{ opacity: 1;}
  8. .title-box{ display: flex; align-items: center; font-size: 26rpx; font-weight: bold;}
  9. .warn{ margin-top: 100rpx; text-align: center;}
  10. .icon-add{ margin-left: 15rpx; display: block; width: 124rpx; height: 124rpx;}
  11. .student-item{ display: flex; flex-wrap: wrap;}
  12. .student-list{ position: relative;}
  13. .student-list .v1{ margin-top: 10rpx; text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-size: 22rpx; color: #777;}
  14. .student-photo{ margin: 0 auto; display: block; width: 124rpx; height: 124rpx; border-radius: 50%;}
  15. .student-box{ padding: 30rpx 0 45rpx 0; display: grid; grid-template-columns: repeat(4, 1fr); grid-gap: 20rpx 0;}
  16. .record-white-box{ margin-top: 30rpx; padding: 22rpx}
  17. .title-box,.title-txt-part{ display: flex; align-items: center;}
  18. .icon-close-black{ display: block; width: 28rpx; height: 16rpx;}
  19. .icon-close-black2{ display: block; width: 28rpx; height: 28rpx;}
  20. .icon-edit{ margin-left: 10rpx; width: 31rpx; height: 30rpx;}
  21. .yellow-fence{ margin-right: 10rpx; width: 6rpx; height: 30rpx; background: #33a9ff; border-radius: 3rpx;}
  22. .title-txt-part{ flex: 1; font-size: 28rpx; font-weight: bold;}
  23. .title-input{ padding-left: 16rpx; width: 360rpx; height: 60rpx; border:1rpx solid #ddd; border-radius: 10rpx; font-size: 26rpx;}
  24. .material-box{ margin-top: 22rpx; display: flex; justify-content: flex-start; flex-wrap: wrap;}
  25. .upload-box{ margin: 0 25rpx 25rpx 0; padding: 0; display: flex; justify-content: center; align-items: center; width: 310rpx; height: 186rpx; background: #f0f0f0; font-size: 25rpx; color: #111; border: 0; border-radius: 22rpx;}
  26. button::after {border: none;}
  27. .icon-photo{ margin-right: 10rpx; display: block; width: 93rpx; height: 85rpx;}
  28. .material-list{ position: relative; margin: 0 25rpx 25rpx 0; width: 295rpx; height: 186rpx;}
  29. .material-list-m2{ width: 100%; height: 100%; border-radius: 22rpx;}
  30. .icon-close{ position: absolute; top: 10rpx; right: 10rpx; z-index: 999; display: block; width: 50rpx; height: 50rpx;}
  31. .add-box{ margin-top: 30rpx; display: flex; justify-content: center; align-items: center; display: flex; font-size: 28rpx; color: #33a9ff;}
  32. .save-btn{ margin: 100rpx auto 0 auto; width: 330rpx; height: 84rpx; text-align: center; line-height: 84rpx; background: #33a9ff; font-size: 30rpx; color: #111; font-weight: bold; border-radius: 42rpx;}
  33. .textarea-box-wrap{ position: relative; margin-top: 22rpx; padding: 22rpx 22rpx 100rpx 22rpx; background: #f0f0f0; border-radius: 10rpx;}
  34. .textarea-box{ width: 100%; height: 300rpx; box-sizing: border-box; font-size: 25rpx; color: #111;}
  35. .voice-box{ margin-bottom: 20rpx; box-sizing: border-box; background: #f0f0f0; font-size: 25rpx; color: #111;}
  36. .videoBtn {width: 50%;}
  37. .videoBtn text{color:#fff;}
  38. .videoBtnBg {background: #bdb4b4;}
  39. .icon-record{ display: block; width: 70rpx; height: 70rpx;}
  40. .textarea-box-footer{ position: absolute; bottom: 0; left: 0; display: flex; justify-content: center; align-items: center; width: 100%; height: 100rpx;}
  41. .record-btn{ margin: 0; padding: 0; width: 70rpx; height: 70rpx; background: transparent; border-radius: 50%;}
  42. button::after{border: none;}
  43. .record-list{ padding-left: 18rpx; display: flex; align-items: center; box-sizing: border-box; width: 640rpx; height: 74rpx; background: #fff; color: #19b2ff; border-radius: 18rpx;}
  44. .icon-video{ display: block; width: 56rpx; height: 55rpx;}
  45. .record-list .t1{ margin: 0 22rpx;}
  46. .record-txt{ padding:10rpx 10rpx 0 10rpx; font-size: 24rpx; color: #19b2ff;}
  47. .record-item{ margin-bottom: 22rpx;}
  48. .record-item:last-child{ margin-bottom: 0;}
  49. .icon-txt{ display: block; width: 60rpx; height: 61rpx;}
  50. .icon-del{ margin-top: 10rpx; display: block; width: 41rpx; height: 53rpx;}
  51. .pos-box{ position: absolute; left: 50%; z-index: 999; transform: translateX(-50%); display: flex; align-items: center; width: 300rpx; height: 140rpx; background: #19b2ff; border-radius: 14rpx;}
  52. .pos-box-lef,.pos-box-rig{ flex: 1; height: 140rpx; display: flex; flex-direction: column; justify-content: center; align-items: center; font-size: 24rpx; color: #fff;}
  53. .pos-box-lef .t1,.pos-box-rig .t1{ margin-top: 6rpx;}
  54. .icon-arrow-up,.icon-arrow-down{ display: block; width: 28rpx; height: 19rpx;}
  55. .icon-arrow-down{ position: absolute; bottom: -19rpx; left: 50%; transform: translateX(-50%);}
  56. .icon-arrow-up{ position: absolute; top: -19rpx; left: 50%; transform: translateX(-50%);}
  57. .mask{ position: fixed; z-index: 99; top: 0; right: 0; bottom: 0; left: 0; background: transparent}
  58. .icon-check{display: block; width: 42rpx; height: 42rpx;}
  59. .icon-check{ position: absolute; top: 0; right: 0;}
  60. .icon-arrow-down{ display: block; width: 24rpx; height: 24rpx;}
  61. .close-box{ width: 40rpx; height: 40rpx; display: flex; justify-content: center; align-items: center;}
  62. .no-graphs{ padding: 30rpx 20rpx; font-size: 24rpx; color: #666;}
  63. .observe-txt{ white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-size: 26rpx; color: #666;}
  64. .textarea-box2{ padding: 20rpx; width: 100%; height: 300rpx; box-sizing: border-box; background: #f0f0f0; font-size: 26rpx; border-radius: 10rpx;}
  65. .textarea-foot{ padding: 10rpx 10rpx 0 10rpx; display: flex; justify-content: space-between; font-size: 22rpx; color: #777;}
  66. .check-list{ margin: 25rpx 0 10rpx 0; display: flex; justify-content: space-between;}
  67. .check-list-lef{ font-size: 26rpx; color: #333;}
  68. .check-list-rig{ display: flex; font-size: 28rpx; color: #777;}
  69. .theme-list{ display: flex; align-items: center; height: 80rpx; border-bottom: 1rpx dashed #ddd;}
  70. .icon-checkbox{ display: block; width: 40rpx; height: 40rpx;}
  71. .theme-list .v1{ margin: 0 20rpx; width: 300rpx; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-size: 28rpx; font-weight: bold; color: #333;}
  72. .theme-list .v2{ font-size: 26rpx; color: #666;}
  73. .theme-list:last-child{ border-bottom: 0;}
  74. .scroll-box{ margin-top: 20rpx; white-space: nowrap;}
  75. .domain-first,.domain-second-list{ margin-right: 10rpx; padding: 0 30rpx; height: 60rpx; line-height: 60rpx; white-space: nowrap; border-radius: 12rpx; background: rgba(51,169,255, 0.3); font-size: 26rpx; color: #333;}
  76. .domain-first.active,.domain-second-list.active{background: rgba(51,169,255, 1); color: #fff;}
  77. .domain-first{ position: relative; overflow: hidden; display: inline-block;}
  78. .corner-mark{ position: absolute; bottom: 0; right: 0; width: 35rpx; height: 33rpx;}
  79. .domain-second-list{ background: rgba(51,169,255, 0.1);}
  80. .domain-second-list.active{background: rgba(51,169,255, 0.7)}
  81. .domain-second{ margin-top: 30rpx; padding: 20rpx 0 0 0; display: flex; flex-wrap: wrap; border-top: 1px solid #eee;}
  82. .domain-second-list{ margin-bottom: 10rpx;}
  83. .domain-three-item{ margin-top: 20rpx;}
  84. .domain-three-title{ margin-bottom: 20rpx; padding: 0 20rpx; display: flex; justify-content: space-between; align-items: center; height: 70rpx; line-height: 70rpx; border: 1px solid #eee; border-radius: 12rpx;}
  85. .domain-three-title .v1{ font-size: 26rpx; color: #333;}
  86. .domain-three-title .v2{ font-size: 24rpx; color: #999;}
  87. .domain-three-list{ margin-bottom: 20rpx; display: flex;}
  88. .domain-three-list .v1{ margin: 0 10rpx; width: 100rpx; line-height: 40rpx; font-size: 24rpx; color: #666;}
  89. .domain-three-list .v2{ margin-left:20rpx; width: 0; flex: 1; line-height: 36rpx; font-size: 24rpx; color: #666;}
  90. .domain-three-list .v2.active{ color: rgb(0, 0, 99); font-weight: bold;}
  91. .close-box-str{ padding: 40rpx 20rpx; font-size: 26rpx; color: #666; white-space: nowrap; text-overflow: ellipsis; overflow: hidden;}
  92. .package-footer{ margin-top: 20rpx; text-align: center; font-size: 24rpx; color: #999;}
  93. .ones-aline{ margin: 0 15rpx;}
  94. .footer{ display: flex; justify-content: space-evenly;}
  95. .footer .v1,.footer .v2,.footer .v3{ margin: 0 25rpx; flex: 1; height: 80rpx; text-align: center; line-height: 80rpx; font-size: 30rpx; border-radius: 50rpx;}
  96. .footer .v1,.footer .v3{ background: #b1b2b9; color: #fff;}
  97. .footer .v2{ background: #33a9ff; color: #fff;}
  98. .record-footer{ margin-top: 30rpx; padding: 20rpx 0;}
  99. .picker{ text-decoration: underline;}
  100. .student-number{ margin-left: 20rpx; font-weight: 400; font-size: 26rpx; color: #777;}
  101. .up-box{ display: flex; justify-content: center; align-items: center; height: 50rpx; background: #fff; border-radius: 10rpx;}
  102. .up-box .icon-close-black{ width: 28rpx; height: 16rpx;}
  103. .student-list2{ position: relative; min-height: 140rpx;}
  104. .student-list2 .v1{ margin-top: 10rpx; text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-size: 20rpx; color: #111;}
  105. .student-photo2{ margin: 0 auto; display: block; width: 100rpx; height: 100rpx; border-radius: 50%;}
  106. .more-box{ width: 100%; height: 100%; display: flex; justify-content: center; align-items: center;}
  107. .scroll-class-box{ margin: 20rpx 0; white-space: nowrap;}
  108. .scroll-class-list{ margin-right: 10rpx; padding: 0 30rpx; display: inline-block; height: 60rpx; line-height: 60rpx; white-space: nowrap; border-radius: 12rpx; background: rgba(25, 178, 255, 0.3); font-size: 26rpx; color: #333;}
  109. .scroll-class-list.active{background: rgba(25, 178, 255, 1); color: #fff;}
  110. .icon-add-txt{ margin-right: 14rpx; width: 45rpx; height: 45rpx; background: #33a9ff; text-align: center; line-height: 45rpx; font-size: 28rpx; color: #fff; border-radius: 50%;}
  111. .only-box{display: flex; justify-content: space-between;}
  112. .mt-20{ margin-top: 20rpx;}
  113. .icon-ai{ display: block; width: 60rpx; height: 60rpx;}
  114. .ai-wrap .v1,.ai-box .v1{ font-size: 20rpx; color: #33a9ff;}
  115. .ai-wrap{ padding-bottom: 8rpx; display: flex; flex-direction: column; justify-content: center; align-items: center; background: #f0f0f0; border-radius: 0 0 10rpx 10rpx;}
  116. .ai-box{ margin-right: 60rpx;}
  117. .icon-add2{ margin-right: 14rpx; display: block; width: 44rpx; height: 45rpx;}
  118. .ai-mask{ position: fixed; z-index: 99; left: 0; bottom:0; width: 750rpx; height: 100vh; background: rgba(0, 0, 0, 0.3);}
  119. .ai-pop{ position: fixed; top: 50%; left: 30rpx; z-index: 100; transform: translateY(-50%); width: 690rpx; min-height: 400rpx; background: #fff; border-radius: 10rpx;}
  120. .ai-pop-cont{ margin: 29rpx 0 0 30rpx; width: 630rpx; height: 300rpx; border-radius: 10rpx;}
  121. .ai-pop-footer{ padding: 20rpx 0; display: flex; justify-content: center;}
  122. .ai-pop-footer .v1,.ai-pop-footer .v2,.ai-pop-footer .v3{ margin: 0 25rpx; flex: 1; height: 60rpx; text-align: center; line-height: 60rpx; font-size: 30rpx; border-radius: 30rpx;}
  123. .ai-pop-footer .v1{ background: #b1b2b9; color: #fff;}
  124. .ai-pop-footer .v2,.ai-pop-footer .v3{ background: #33a9ff; color: #fff;}

个人记录项目使用的 想使用的同学自己扣代码吧

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/525141
推荐阅读
相关标签
  

闽ICP备14008679号