article.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507
  1. import common from '../../utils/util';
  2. import main from '../../utils/main';
  3. import animation from '../../utils/animation';
  4. const Theme=[{
  5. "Name":"DarkColor",
  6. "backgroundColor": "#004433",
  7. "color":"#C1E1C1",
  8. "frontColor": '#ffffff',
  9. },{
  10. "Name":"LightColor",
  11. "backgroundColor": "#D0ECD3",
  12. "color":"#151815",
  13. "frontColor": '#000000',
  14. }
  15. ];
  16. const app = getApp();
  17. Page({
  18. data: {
  19. Words:"",
  20. IsShowFirstOpen:true,
  21. IsBuilding:false,
  22. IsBuildError:false,
  23. IsShowLightColor:false,
  24. IsShowKeyword:true,//显示关键词
  25. IsShowQuestion:false,
  26. IsShowTranslate:false,
  27. IsShowSetting:false,
  28. IsShowRemind:false,
  29. remindAnimation: "", // 翻译弹窗动画类
  30. CurrentQuestionIndex:0,
  31. swiperHeight: "526rpx",
  32. lastTapTime: 0, // 记录上一次点击的时间,用于检测双击
  33. CountDown:30,//倒计时秒数
  34. },
  35. onLoad: function (options) {
  36. let that = this;
  37. let words=app.globalData.SelectedWords.join(",");
  38. let wordsStr=app.globalData.SelectedWords.join(" ");
  39. const hiddenhelp=wx.getStorageSync('HiddenArticleFirstOpen');
  40. let IsShowKeyword=wx.getStorageSync('IsShowKeyword');
  41. if (IsShowKeyword===""){
  42. IsShowKeyword=true;
  43. wx.setStorageSync('IsShowKeyword', true);
  44. }
  45. let IsShowLightColor=wx.getStorageSync('IsShowLightColor');
  46. if (!IsShowLightColor){
  47. IsShowLightColor=false;
  48. }
  49. that.setData({
  50. Containnerheight: main.getWindowHeight(),
  51. Words:words,
  52. WordsStr:wordsStr,
  53. Level:options.Level,
  54. ArticleStyle:options.ArticleStyle,
  55. AIVersion:options.AIVersion,
  56. IsShowFirstOpen:!hiddenhelp,
  57. IsShowLightColor:IsShowLightColor,
  58. IsShowKeyword:IsShowKeyword,
  59. IsBuildError:false,
  60. IsBuilding:false,
  61. });
  62. if (options.ID)
  63. that.getArticleByID(options.ID);
  64. else
  65. that.init(options);
  66. that.setTheme();
  67. // //测试
  68. // that.setData({
  69. // IsBuilding:true,
  70. // });
  71. // that.getChoicenessArticle();
  72. main.checkGenerating();
  73. },
  74. getArticleByID:function(id){
  75. let that=this;
  76. main.getData('GetYJBDCArticleList?UserID=' + app.globalData.userInfo.UserID+'&ID='+id, function (data) {
  77. if (data) {
  78. data=data[0];
  79. that.setData({
  80. Words:data.Words,
  81. Level:data.Level,
  82. ArticleStyle:data.ArticleStyle,
  83. CreateTime:data.CreateTime,
  84. ID:id,
  85. });
  86. let content=data.JSONString;
  87. that.updateData(content);
  88. }
  89. });
  90. },
  91. init:function(options){
  92. let that=this;
  93. let interval=0;
  94. that.data.CountDown=30;
  95. //1.5文章生成时间长
  96. if (that.data.AIVersion=="1.5"){
  97. that.setData({
  98. CountDown:60,
  99. });
  100. }
  101. interval = setInterval(function(){
  102. that.setData({
  103. CountDown:--that.data.CountDown,
  104. });
  105. if (that.data.CountDown<=0)
  106. clearInterval(interval);
  107. },1200);
  108. that.setData({
  109. IsBuilding:true
  110. });
  111. app.globalData.Generating=true;
  112. let words=app.globalData.SelectedWords.join(",");
  113. main.postData('GenerateArticle?UserID='+app.globalData.userInfo.UserID, {
  114. Words:words,
  115. Level:that.data.Level,
  116. ArticleStyle:that.data.ArticleStyle,
  117. AIVersion:that.data.AIVersion
  118. }, function (data) {
  119. app.globalData.Generating=false;
  120. if (data){
  121. if (data=="-1"){
  122. that.setData({
  123. IsBuildError:true,
  124. CreateTime:common.formatDateCHS(common.formatTime(new Date()),true),
  125. });
  126. }
  127. else{
  128. let content=data;
  129. that.updateData(content);
  130. that.setData({
  131. IsBuilding:false,
  132. });
  133. }
  134. clearInterval(interval);
  135. }
  136. });
  137. that.getChoicenessArticle();
  138. },
  139. //得到精选文章
  140. getChoicenessArticle:function(){
  141. let that=this;
  142. main.getData('GetYJBDCArticleList?IsChoiceness=1', function (data) {
  143. if (data) {
  144. that.setData({
  145. ChoicenessList:data,
  146. });
  147. }
  148. });
  149. },
  150. updateData:function(content){
  151. let that=this;
  152. //console.log(content);
  153. if (typeof content === 'string') {
  154. content = JSON.parse(content);
  155. }
  156. if (typeof content === 'string') {
  157. content = JSON.parse(content);
  158. }
  159. let hl = that.data.IsShowKeyword ? "highlight" : "nonelight";
  160. // 初始化ArticleEnglishArr数组
  161. content.ArticleEnglishArr = [];
  162. for(let i=0; i<content.ArticleEnglish.length; i++){
  163. // 确保每个句子末尾有空格,避免和下一句紧挨着
  164. const sentence = content.ArticleEnglish[i] + " ";
  165. // 按长度从长到短排序单词,确保先匹配较长的词组
  166. const sortedWords = [...content.FormsOfWords].sort((a, b) => b.length - a.length);
  167. // 创建一个句子的分段数组
  168. let segments = [{
  169. Sentence: sentence,
  170. CSS: ""
  171. }];
  172. // 对每个单词进行处理
  173. for(let j=0; j<sortedWords.length; j++){
  174. const word = sortedWords[j];
  175. // 创建一个新的分段数组,用于存储处理后的结果
  176. let newSegments = [];
  177. // 处理每个现有分段
  178. for(let k=0; k<segments.length; k++){
  179. const segment = segments[k];
  180. // 如果当前分段已经被标记为高亮,则不再处理
  181. if(segment.CSS !== ""){
  182. newSegments.push(segment);
  183. continue;
  184. }
  185. const text = segment.Sentence;
  186. // 使用正则表达式查找单词边界
  187. const regex = new RegExp(`\\b${word}\\b`, 'gi');
  188. let lastIndex = 0;
  189. let match;
  190. // 查找所有匹配项
  191. while((match = regex.exec(text)) !== null){
  192. // 添加匹配前的文本
  193. if(match.index > lastIndex){
  194. newSegments.push({
  195. Sentence: text.substring(lastIndex, match.index),
  196. CSS: ""
  197. });
  198. }
  199. // 添加匹配的单词(高亮)
  200. newSegments.push({
  201. Sentence: match[0],
  202. CSS: hl
  203. });
  204. lastIndex = match.index + match[0].length;
  205. }
  206. // 添加最后一个匹配后的文本
  207. if(lastIndex < text.length){
  208. newSegments.push({
  209. Sentence: text.substring(lastIndex),
  210. CSS: ""
  211. });
  212. }
  213. }
  214. // 更新分段数组
  215. segments = newSegments;
  216. }
  217. // 将分段数组添加到ArticleEnglishArr
  218. content.ArticleEnglishArr.push(segments);
  219. }
  220. for(let i=0;i<content.Question.length;i++){
  221. for(let j=0;j<content.Question[i].OptionsEnglish.length;j++){
  222. let str=content.Question[i].OptionsChinese[j];
  223. content.Question[i].OptionsChinese[j]=str.substr(2);
  224. }
  225. let char = content.Question[i].Answer;
  226. let asciiCode = char.charCodeAt(0);
  227. content.Question[i].AnswerNumber=asciiCode-65;
  228. content.Question[i].IsShowAnswer=false;
  229. }
  230. that.setData({
  231. Content:content,
  232. });
  233. },
  234. setTheme:function(){
  235. let that=this;
  236. const css=Theme[that.data.IsShowLightColor?1:0];
  237. wx.setNavigationBarColor({
  238. frontColor: css.frontColor,
  239. backgroundColor: css.backgroundColor,
  240. });
  241. wx.setBackgroundColor({
  242. backgroundColor: css.backgroundColor,
  243. backgroundColorTop:css.backgroundColor,
  244. backgroundColorBottom:css.backgroundColor,
  245. });
  246. that.setData({
  247. ThemeCSS:css.Name,
  248. });
  249. wx.setStorageSync('IsShowLightColor', that.data.IsShowLightColor);
  250. },
  251. closeHelp:function(){
  252. this.setData({
  253. IsShowFirstOpen:false,
  254. });
  255. wx.setStorageSync('HiddenArticleFirstOpen', true);
  256. },
  257. selectedAnswer:function(e){
  258. let that=this;
  259. const question=e.currentTarget.dataset.question;
  260. const index=e.currentTarget.dataset.index;
  261. if (that.data.Content.Question[question].UserAnswer==index)
  262. that.data.Content.Question[question].UserAnswer=-1;
  263. else
  264. that.data.Content.Question[question].UserAnswer=index;
  265. that.setData({
  266. Content:that.data.Content,
  267. });
  268. },
  269. showData:function(e){
  270. let that=this;
  271. let name=e.currentTarget.dataset.name;
  272. this.data[name] = !this.data[name];
  273. this.setData(this.data);
  274. if (name=="IsShowKeyword"){
  275. that.setShowKeyword();
  276. }
  277. else if (name=="IsShowLightColor"){
  278. that.setTheme();
  279. }
  280. else if (name=="IsShowAnswer"){
  281. let index=e.currentTarget.dataset.index;
  282. let content=that.data.Content;
  283. content.Question[index].IsShowAnswer=!content.Question[index].IsShowAnswer;
  284. that.setData({
  285. Content:content,
  286. });
  287. }
  288. },
  289. setShowKeyword:function(){
  290. let that=this;
  291. let content=that.data.Content;
  292. let source="highlight",target="nonelight";
  293. if (that.data["IsShowKeyword"]){
  294. source="nonelight";
  295. target="highlight";
  296. }
  297. for(let i=0;i<content.ArticleEnglishArr.length;i++){
  298. let obj=content.ArticleEnglishArr[i];
  299. let arr=[];
  300. for(let j=0;j<obj.length;j++){
  301. if (obj[j].CSS==source)
  302. obj[j].CSS=target;
  303. }
  304. }
  305. for(let i=0;i<content.ArticleEnglish.length;i++){
  306. content.ArticleEnglish[i]=common.ReplaceAllString(content.ArticleEnglish[i],source,target);
  307. }
  308. that.setData({
  309. Content:content,
  310. });
  311. wx.setStorageSync('IsShowKeyword', that.data.IsShowKeyword);
  312. },
  313. nextQuestion:function(e){
  314. if (this.data.CurrentQuestionIndex+1<this.data.Content.Question.length){
  315. this.data.CurrentQuestionIndex=this.data.CurrentQuestionIndex+1;
  316. this.setData({
  317. CurrentQuestionIndex:this.data.CurrentQuestionIndex,
  318. });
  319. }
  320. },
  321. updateQuestionIndex:function(e){
  322. this.setData({
  323. CurrentQuestionIndex:e.detail.current,
  324. });
  325. console.log(e.detail.current);
  326. },
  327. onContainerTap: function() {
  328. const currentTime = new Date().getTime();
  329. const lastTapTime = this.data.lastTapTime;
  330. const timeDiff = currentTime - lastTapTime;
  331. // 如果两次点击的时间间隔小于300毫秒,则认为是双击
  332. if (timeDiff < 300 && timeDiff > 0) {
  333. console.log('双击事件触发');
  334. // 在这里添加双击事件的处理逻辑
  335. // 例如:切换翻译显示状态
  336. this.showData({currentTarget:{dataset:{name:"IsShowTranslate"}}});
  337. }
  338. // 更新上一次点击的时间
  339. this.setData({
  340. lastTapTime: currentTime
  341. });
  342. },
  343. //生成PDF文件
  344. //访问服务器的GeneratePDF接口,提交this.data.Content数据,获得一个生成好的pdf文件,服务端的代码已经生成好
  345. generatePDF: function(e) {
  346. let that = this;
  347. //debugger;
  348. that.data.Content.Words=that.data.Words;
  349. that.data.Content.Level=that.data.Level;
  350. that.data.Content.ArticleStyle=that.data.ArticleStyle;
  351. that.data.Content.CreateTime=that.data.CreateTime;
  352. let url = common.Encrypt("GeneratePDF");
  353. url =app.globalData.serverUrl + url;
  354. wx.request({
  355. url: url,
  356. method: "POST",
  357. data: {
  358. Content: that.data.Content,
  359. },
  360. responseType: 'arraybuffer', // 确保响应类型为arraybuffer
  361. success: function(res) {
  362. // 将arraybuffer转为临时文件
  363. const fsm = wx.getFileSystemManager();
  364. let time=common.formatTime(new Date(),"-");
  365. time=common.ReplaceAllString(time,"-","");
  366. time=common.ReplaceAllString(time,":","");
  367. time=common.ReplaceAllString(time," ","_");
  368. time=time.substring(2,time.length-2);
  369. const tempFilePath = `${wx.env.USER_DATA_PATH}/语境背单词_${time}.pdf`;
  370. try {
  371. fsm.writeFileSync(
  372. tempFilePath,
  373. res.data,
  374. 'binary'
  375. );
  376. // 直接使用临时文件路径,不再尝试永久保存
  377. console.log('文件已生成:', tempFilePath);
  378. // 打开PDF文件预览
  379. wx.openDocument({
  380. filePath: tempFilePath,
  381. fileType: 'pdf',
  382. showMenu: true, // 显示右上角菜单,可以分享
  383. success: function() {
  384. },
  385. fail: function(error) {
  386. console.error('打开文档失败:', error);
  387. wx.showToast({
  388. title: '打开文件失败',
  389. icon: 'none'
  390. });
  391. }
  392. });
  393. } catch (error) {
  394. console.error('写入文件失败:', error);
  395. wx.showToast({
  396. title: '写入文件失败',
  397. icon: 'none'
  398. });
  399. }
  400. },
  401. fail: function(err) {
  402. console.error('请求GeneratePDF接口失败:', err);
  403. wx.showToast({
  404. title: '网络错误,请稍候重试',
  405. icon: 'none'
  406. });
  407. }
  408. });
  409. },
  410. // 处理导航栏返回按钮点击事件
  411. onUnload: function() {
  412. if (!this.data.ID){
  413. app.globalData.SelectedWords=[];
  414. wx.navigateBack({
  415. delta: 1,
  416. });
  417. }
  418. },
  419. onLongPress: function(e) {
  420. let that = this;
  421. let strType=e.currentTarget.dataset.strtype;
  422. let selectedIndex=e.currentTarget.dataset.index;
  423. let selectedIndex2=e.currentTarget.dataset.index2;
  424. let engSentence,chnSentence;
  425. if (strType=="article"){
  426. //console.log("选中的句子索引:", selectedIndex);
  427. //console.log("选中的句子:", that.data.Content.ArticleEnglish[selectedIndex]);
  428. engSentence=that.data.Content.ArticleEnglish[selectedIndex];
  429. chnSentence=that.data.Content.ArticleChinese[selectedIndex];
  430. }
  431. else if (strType=="question"){
  432. engSentence=that.data.Content.Question[selectedIndex].QuestionEnglish;
  433. chnSentence=that.data.Content.Question[selectedIndex].QuestionChinese;
  434. }
  435. else if (strType=="option"){
  436. engSentence=that.data.Content.Question[selectedIndex].OptionsEnglish[selectedIndex2];
  437. chnSentence=that.data.Content.Question[selectedIndex].OptionsChinese[selectedIndex2];
  438. }
  439. this.setData({
  440. EnglishSentence:engSentence,
  441. ChineseSentence:chnSentence,
  442. });
  443. // 使用动画工具函数显示弹窗,并指定显示动画
  444. animation.toggleRemindWithAnimation(this, {
  445. showAnimation: 'remind-slide-up'
  446. });
  447. },
  448. showRemind:function(e){
  449. animation.toggleRemindWithAnimation(this, {
  450. showAnimation: 'remind-slide-down'
  451. });
  452. },
  453. goto: function (e) {
  454. let that=this;
  455. var url=e.currentTarget.dataset.url;
  456. wx.navigateTo({
  457. url: url,
  458. });
  459. },
  460. onShareAppMessage: function () {
  461. return {
  462. title: app.globalData.ShareTitle,
  463. path: app.globalData.SharePath + '?UserID=' + app.globalData.userInfo.UserID,
  464. imageUrl: app.globalData.ShareImage,
  465. }
  466. },
  467. })