article.js 14 KB

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