hanziController.js 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173
  1. import moment from 'moment';
  2. import commonModel from '../../model/commonModel.js';
  3. import hanzi from '../../model/hanzi.js';
  4. import config from '../../config/index.js';
  5. import _ from 'lodash';
  6. import axios from 'axios';
  7. import { Encrypt, Decrypt } from '../../util/crypto/index.js';
  8. import { stringUtils } from '../../util/stringClass.js';
  9. import WXBizDataCrypt from '../../util/WXBizDataCrypt.js';
  10. import { globalCache } from '../../util/GlobalCache.js';
  11. import constantClass from '../../util/constant/index.js';
  12. import gm from 'gm';
  13. import fs from 'fs';
  14. import { promises as fsPromises } from 'fs';
  15. import COS from 'cos-nodejs-sdk-v5';
  16. const imageMagick = gm.subClass({ imageMagick: true });
  17. export async function HanziLogin(ctx) {
  18. let param = ctx.request.body;
  19. if (param.param) {
  20. const paramStr = Decrypt(param.param, config.urlSecrets.aes_key, config.urlSecrets.aes_iv);
  21. //console.log("paramStr:"+paramStr);
  22. param = JSON.parse(paramStr);
  23. }
  24. const code = param.Code;
  25. //console.log("code:"+code);
  26. const url = `https://api.weixin.qq.com/sns/jscode2session?appid=${config.wx.hanzi_appid}&secret=${config.wx.hanzi_appsecret}&js_code=${code}&grant_type=authorization_code`;
  27. let result = await axios.get(url)
  28. .then(res => {
  29. const json = res.data;
  30. //console.log("json:"+json);
  31. if (json && json.openid) {
  32. param.OpenID = json.openid;
  33. param.sessionKey = json.session_key;
  34. if (json.unionid)
  35. param.UnionID = json.unionid;
  36. return {errcode: 10000};
  37. }
  38. else {
  39. return json;
  40. }
  41. })
  42. .catch(err => {
  43. return {errcode: 101, errStr: err};
  44. });
  45. if (result.errcode == 10000) {
  46. delete param.Code;
  47. if (param.sessionKey && param.iv && param.encryptedData){
  48. //console.log("param.sessionKey:"+param.sessionKey);
  49. const pc = new WXBizDataCrypt(config.wx.hanzi_appid, param.sessionKey);
  50. const dataUnionID = pc.decryptData(param.encryptedData , param.iv);
  51. //console.log(dataUnionID);
  52. param.UnionID = dataUnionID.unionId;
  53. }
  54. delete param.sessionKey;
  55. delete param.iv;
  56. delete param.encryptedData;
  57. //todo
  58. //param.OpenID="o4UHq4gaNlHfdTWxgl3fTgC1mFsI";
  59. let userList = await hanzi.GetUsersInfo(param);
  60. if (userList.length > 0) {
  61. param.LastLoginTime = new Date();
  62. const time1 = moment(userList[0].ProductServiceTime).format('YYYY-MM-DD HH:mm:ss');
  63. const time3 = moment().format('YYYY-MM-DD HH:mm:ss');
  64. if (time1 < time3)
  65. param.IsMember = 0;
  66. delete param.Introducer;
  67. delete param.UserSource;
  68. delete param.SourceID;
  69. //console.log(param.NickName);
  70. if (param.NickName == "陌生用户") {
  71. delete param.NickName;
  72. delete param.AvatarUrl;
  73. delete param.Language;
  74. delete param.Gender;
  75. delete param.City;
  76. delete param.Province;
  77. delete param.Country;
  78. }
  79. await hanzi.UpdateUsers(param);
  80. userList = await hanzi.GetUsersInfo(param);
  81. }
  82. else {
  83. param.NickName = "陌生用户";
  84. param.AvatarUrl = "../images/userface_default.png";
  85. param.CreateTime = new Date();
  86. param.LastLoginTime = param.CreateTime;
  87. param.ProductServiceTime = param.CreateTime;
  88. const inseredID = await hanzi.AddUsers(param);
  89. userList = await hanzi.GetUsersInfo(param);
  90. }
  91. delete userList[0].OpenID;
  92. delete userList[0].UnionID;
  93. //产品支付是否显示
  94. if (param.ProgramVersion) {
  95. let param2 = {
  96. ProgramID: 106,
  97. Version: param.ProgramVersion,
  98. };
  99. let result3 = await commonModel.GetProductVersionList(param2);
  100. if (result3) {
  101. if ((param2.Version == result3[0].Version && result3[0].IsShowPay <= 0)
  102. || param2.Version > result3[0].Version) {
  103. userList[0].IsShow = result3[0].IsShowPay;
  104. }
  105. else {
  106. userList[0].IsShow = 1;
  107. }
  108. //针对iphone测试用户,永远是无支付状态
  109. if (userList[0].Brand == 'iPhone' && userList[0].WXLanguage == 'en-US'
  110. && userList[0].UserSource == '1001' && userList[0].IsPay == 0) {
  111. userList[0].IsShow = 0;
  112. }
  113. //针对微信测试用户,永远是无支付状态
  114. if ((userList[0].UserSource=='1001' && userList[0].System=="iOS 10.0.1")
  115. || (!userList[0].UserSource && (!userList[0].LastUserSource || userList[0].LastUserSource>10000))
  116. || userList[0].NickName.indexOf("dgztest")>=0){
  117. userList[0].IsShow=-1;
  118. }
  119. if (userList[0].IsMember===1)
  120. userList[0].IsShow=1;
  121. }
  122. }
  123. result = {errcode: 10000, result: userList[0]};
  124. }
  125. ctx.body = result;
  126. }
  127. //新增汉字记录
  128. export async function AddHanziRecord(ctx) {
  129. const param = ctx.request.body;
  130. const inseredID = await hanzi.AddHanziRecord(param);
  131. ctx.body = {errcode: 10000, result: inseredID};
  132. }
  133. //更新汉字记录
  134. export async function UpdateHanziRecord(ctx) {
  135. const param = ctx.request.body;
  136. await hanzi.UpdateHanziRecord(param);
  137. ctx.body = {errcode: 10000};
  138. }
  139. //新增或删除汉字完成结果
  140. export async function UpdateHanziFinished(ctx) {
  141. const param = ctx.request.body;
  142. if (param.Style == "undefined")
  143. param.Style = "";
  144. if (param.IsFinished) {
  145. delete param.IsFinished;
  146. if (param.UserID) {
  147. await hanzi.AddHanziFinished(param);
  148. }
  149. }
  150. else {
  151. delete param.IsFinished;
  152. if (param.UserID) {
  153. await hanzi.DeleteHanziFinished(param);
  154. }
  155. }
  156. ctx.body = {errcode: 10000};
  157. }
  158. //得到用户完成记录
  159. export async function GetHanziFinishedData(ctx) {
  160. const param = {
  161. UserID: ctx.query.UserID || 0,
  162. };
  163. if (param.UserID=="undefined")
  164. param.UserID=0;
  165. const result = await hanzi.GetHanziFinishedData(param);
  166. if (result && result.length > 0)
  167. ctx.body = {"errcode": 10000, result: result};
  168. else
  169. ctx.body = {"errcode": 10000};
  170. }
  171. //得到汉字数据(1.6.9以后识字小程序持续使用)
  172. export async function GetHanziAll0124(ctx) {
  173. const param = {
  174. UpdateTime: ctx.query.UpdateTime,
  175. HasEnglish: ctx.query.HasEnglish || false,
  176. HasHanziWrite: ctx.query.HasHanziWrite || false,
  177. };
  178. const updateTimeList = await commonModel.GetDataUpdateStatus();
  179. const updateTime = moment(updateTimeList[5].UpdateTime).format('YYYY.MM.DD HH:mm:ss');
  180. if (param.UpdateTime != updateTime) {
  181. let result = globalCache.get("GetHanziAll");
  182. if (result == 0) {
  183. result = {
  184. UpdateTime: updateTime,
  185. }
  186. let readList = [];
  187. const arrBooks = await hanzi.GetHanziBooks();
  188. const arrUnits = await hanzi.GetHanziUnits();
  189. const arrWords = await hanzi.GetHanziWords();
  190. const arr = [];
  191. for (let i = 0; i < arrBooks.length; i++) {
  192. arrBooks[i].Units = [];
  193. if (arrBooks[i].ID >= 61 && arrBooks[i].ID <= 72) {
  194. if (arrBooks[i].ID == 71)
  195. arrBooks[i].ID = 23;
  196. if (arrBooks[i].ID == 72)
  197. arrBooks[i].ID = 24;
  198. for (let j = 0; j < arrUnits.length; j++) {
  199. if (arrBooks[i].ID == arrUnits[j].HanziBookID) {
  200. arrUnits[j].Words = [];
  201. for (let n = 0; n < arrUnits[j].Example.length; n++) {
  202. const word = arrUnits[j].Example[n];
  203. for (let k = 0; k < arrWords.length; k++) {
  204. if (word == arrWords[k].Name) {
  205. delete arrWords[k].HanziUnitID;
  206. arrUnits[j].Words.push(arrWords[k]);
  207. break;
  208. }
  209. }
  210. }
  211. delete arrUnits[j].HanziBookID;
  212. arrUnits[j].Title = arrUnits[j].Example.substr(0,4);
  213. arrBooks[i].Units.push(arrUnits[j]);
  214. }
  215. }
  216. if (arrBooks[i].ID == 23)
  217. arrBooks[i].ID = 71;
  218. if (arrBooks[i].ID == 24)
  219. arrBooks[i].ID = 72;
  220. arr.push(arrBooks[i]);
  221. }
  222. }
  223. readList = arr;
  224. readList = JSON.stringify(readList);
  225. readList = Encrypt(readList, config.urlSecrets.aes_key, config.urlSecrets.aes_iv);
  226. result.List = readList;
  227. globalCache.set("GetHanziAll", result, config.BufferMemoryTimeHigh);
  228. console.log("缓存");
  229. }
  230. ctx.body = {"errcode": 10000, result: result};
  231. } else {
  232. const result = {
  233. String: globalCache.get("BaiduToken"),
  234. }
  235. ctx.body = {"errcode": 10000, result: result};
  236. }
  237. }
  238. //得到汉字数据(2.1.60)后使用
  239. export async function GetHanziAll3(ctx) {
  240. const param = {
  241. UpdateTime: ctx.query.UpdateTime,
  242. };
  243. const updateTimeList = await commonModel.GetDataUpdateStatus();
  244. const updateTime = moment(updateTimeList[5].UpdateTime).format('YYYY.MM.DD HH:mm:ss');
  245. if (param.UpdateTime != updateTime) {
  246. let result = globalCache.get("GetHanziAll3");
  247. if (result == 0) {
  248. result = {
  249. UpdateTime: updateTime,
  250. }
  251. let readList = [];
  252. const arrBooks = await hanzi.GetHanziBooks();
  253. const arrUnits = await hanzi.GetHanziUnits();
  254. const arrWords = await hanzi.GetHanziWords();
  255. const arrAncientList = await hanzi.GetAncientChineseProse({IsList:0});
  256. const arrAncientChineseProseSentenct = await hanzi.GetAncientChineseProseSentence({});
  257. const arr = [];
  258. for (let i = 0; i < arrBooks.length; i++) {
  259. arrBooks[i].Units = [];
  260. for (let j = 0; j < arrUnits.length; j++) {
  261. if (arrBooks[i].ID == arrUnits[j].HanziBookID) {
  262. arrUnits[j].Words = [];
  263. //早期识字
  264. if (arrUnits[j].HanziBookID <= 12) {
  265. }
  266. //写字
  267. else if (arrUnits[j].HanziBookID >= 13 && arrUnits[j].HanziBookID <= 24) {
  268. const words = arrUnits[j].Example;
  269. for(let m = 0; m < words.length; m++) {
  270. for (let k = 0; k < arrWords.length; k++) {
  271. if (words[m] == arrWords[k].Name) {
  272. arrUnits[j].Words.push(arrWords[k].Name);
  273. arrUnits[j].Words = _.union(arrUnits[j].Words);
  274. }
  275. }
  276. }
  277. }
  278. //词语
  279. else if (arrUnits[j].HanziBookID >= 43 && arrUnits[j].HanziBookID <= 60) {
  280. const words = arrUnits[j].Example.split(",");
  281. for(let m = 0; m < words.length; m++) {
  282. arrUnits[j].Words.push(words[m]);
  283. }
  284. }
  285. //新识字
  286. else if (arrUnits[j].HanziBookID >= 61 && arrUnits[j].HanziBookID <= 72) {
  287. const words = arrUnits[j].Example;
  288. for(let m = 0; m < words.length; m++) {
  289. for (let k = 0; k < arrWords.length; k++) {
  290. if (words[m] == arrWords[k].Name) {
  291. arrUnits[j].Words.push(arrWords[k].Name);
  292. arrUnits[j].Words = _.union(arrUnits[j].Words);
  293. }
  294. }
  295. }
  296. }
  297. //文言文
  298. else if (arrUnits[j].HanziBookID == 73) {
  299. for(let n = 0; n < arrAncientList.length; n++) {
  300. if (arrUnits[j].Name == arrAncientList[n].Word) {
  301. arrUnits[j].Words.push(arrAncientList[n].Definitions);
  302. }
  303. }
  304. }
  305. //小古文
  306. else if (arrUnits[j].HanziBookID == 86) {
  307. for(let n = 0; n < arrAncientChineseProseSentenct.length; n++) {
  308. if (arrUnits[j].Name == arrAncientChineseProseSentenct[n].Unit) {
  309. for(let m = 0; m < arrAncientChineseProseSentenct[n].Count; m++)
  310. arrUnits[j].Words.push("");
  311. }
  312. }
  313. }
  314. delete arrUnits[j].HanziBookID;
  315. delete arrUnits[j].Example;
  316. delete arrUnits[j].OrderID;
  317. delete arrUnits[j].IsLocked;
  318. delete arrUnits[j].UnitType;
  319. arrBooks[i].Units.push(arrUnits[j]);
  320. }
  321. }
  322. arr.push(arrBooks[i]);
  323. }
  324. readList = arr;
  325. readList = JSON.stringify(readList);
  326. readList = Encrypt(readList, config.urlSecrets.aes_key, config.urlSecrets.aes_iv);
  327. result.List = readList;
  328. globalCache.set("GetHanziAll3", result, config.BufferMemoryTimeHigh);
  329. console.log("缓存");
  330. }
  331. ctx.body = {"errcode": 10000, result: result};
  332. } else {
  333. const result = {
  334. String: globalCache.get("BaiduToken"),
  335. }
  336. ctx.body = {"errcode": 10000, result: result};
  337. }
  338. }
  339. //得到一册书的字词数据
  340. export async function GetHanziByBookID(ctx) {
  341. const param = ctx.request.body;
  342. let result = globalCache.get("GetHanziByBookID?BookID="+param.BookID);
  343. if (result == 0) {
  344. const arrUnits = await hanzi.GetHanziUnits(param);
  345. const arrWords = await hanzi.GetHanziWords();
  346. for (let j = 0; j < arrUnits.length; j++) {
  347. arrUnits[j].Words = [];
  348. //写字
  349. if (arrUnits[j].HanziBookID >= 13 && arrUnits[j].HanziBookID <= 24) {
  350. const words = arrUnits[j].Example;
  351. for(let m = 0; m < words.length; m++) {
  352. for (let k = 0; k < arrWords.length; k++) {
  353. if (words[m] == arrWords[k].Name) {
  354. arrUnits[j].Words.push(arrWords[k].Name);
  355. arrUnits[j].Words = _.union(arrUnits[j].Words);
  356. }
  357. }
  358. }
  359. }
  360. //词语
  361. else if (arrUnits[j].HanziBookID >= 43 && arrUnits[j].HanziBookID <= 60) {
  362. const words = arrUnits[j].Example.split(",");
  363. for(let m = 0; m < words.length; m++) {
  364. arrUnits[j].Words.push(words[m]);
  365. }
  366. }
  367. //新识字
  368. else if (arrUnits[j].HanziBookID >= 61 && arrUnits[j].HanziBookID <= 72) {
  369. const words = arrUnits[j].Example;
  370. for(let m = 0; m < words.length; m++) {
  371. for (let k = 0; k < arrWords.length; k++) {
  372. if (words[m] == arrWords[k].Name) {
  373. arrUnits[j].Words.push(arrWords[k].Name);
  374. arrUnits[j].Words = _.union(arrUnits[j].Words);
  375. }
  376. }
  377. }
  378. }
  379. delete arrUnits[j].HanziBookID;
  380. delete arrUnits[j].OrderID;
  381. delete arrUnits[j].Example;
  382. delete arrUnits[j].UnitType;
  383. delete arrUnits[j].IsLocked;
  384. }
  385. result = arrUnits;
  386. globalCache.set("GetHanziByBookID?BookID="+param.BookID, result, config.BufferMemoryTimeHigh);
  387. console.log("缓存");
  388. }
  389. ctx.body = {"errcode": 10000, result: result};
  390. }
  391. //得到英语数据(2.1.60)后使用
  392. export async function GetSoundErrorArr(ctx) {
  393. const param = {
  394. UpdateTime: ctx.query.UpdateTime,
  395. };
  396. const updateTimeList = await commonModel.GetDataUpdateStatus();
  397. const updateTime = moment(updateTimeList[7].UpdateTime).format('YYYY.MM.DD HH:mm:ss');
  398. if (param.UpdateTime != updateTime) {
  399. const result = {
  400. List: await constantClass.GetSoundErrorArr(),
  401. UpdateTime: updateTime
  402. };
  403. ctx.body = {"errcode": 10000, result: result};
  404. } else {
  405. ctx.body = {"errcode": 10000};
  406. }
  407. }
  408. //得到汉字详细数据
  409. export async function GetHanziDetail(ctx) {
  410. const param = {
  411. ID: ctx.query.ID || 0,
  412. Type: "all",
  413. };
  414. if (param.ID && param.ID > 0) {
  415. let result = globalCache.get("GetHanziDetail?ID=" + param.ID);
  416. if (result == 0) {
  417. const arrWords = await hanzi.GetHanziWords(param);
  418. result = JSON.parse(arrWords[0].Details);
  419. for (let i = 0; i < result.PinYin.length; i++) {
  420. let item = result.PinYin[i].explain;
  421. item = stringUtils.ReplaceAllString(item, "<p>", "");
  422. item = stringUtils.ReplaceAllString(item, "<span>", "");
  423. item = stringUtils.ReplaceAllString(item, "</span>", "");
  424. item = stringUtils.ReplaceAllString(item, "\r", "");
  425. item = stringUtils.ReplaceAllString(item, "\n", "");
  426. const arr = item.split("</p>");
  427. arr.pop();
  428. result.PinYin[i].explain = arr;
  429. }
  430. globalCache.set("GetHanziDetail?ID=" + param.ID, result, config.BufferMemoryTimeHigh);
  431. }
  432. ctx.body = {"errcode": 10000, result: result};
  433. } else {
  434. ctx.body = {"errcode": 10000};
  435. }
  436. }
  437. //得到单元汉字数据
  438. export async function GetHanziUnitWords(ctx) {
  439. const param = {
  440. UnitID: ctx.query.UnitID || 0,
  441. TestType: ctx.query.TestType || "read",
  442. };
  443. let result = globalCache.get("GetHanziUnitWords?UnitID=" + param.UnitID + "&TestType=" + param.TestType);
  444. if (result == 0) {
  445. const unitInfo = await hanzi.GetHanziUnitInfo(param);
  446. //词语部分
  447. if (unitInfo && unitInfo.length > 0 && unitInfo[0].UnitType == 2) {
  448. const words = await hanzi.GetHanziUnitByID(param);
  449. if (words[0] && words[0].Example) {
  450. let words1 = words[0].Example.split(",").join("','");
  451. param.Words = words1;
  452. result = await hanzi.GetMiaoguoLiteracyWords(param);
  453. let temp = "";
  454. let arrTemp = [];
  455. for (let i = 0; i < result.length; i++) {
  456. if (temp != result[i].Word && result[i].JSONString) {
  457. const json = JSON.parse(result[i].JSONString);
  458. const obj = {};
  459. obj.ID = i + 1;
  460. let qustion, answer, tags;
  461. if (param.TestType == "read") {
  462. qustion = result[i].Word;
  463. if (process.env.NODE_ENV == 'development')
  464. console.log(qustion);
  465. answer = "[读 src='" + result[i].Word + "']" + json.CHN.PinYin[0].pinyin + "[/读]\n\n";
  466. answer += json.CHN.PinYin[0].explain;
  467. tags = "怎么念";
  468. obj.FontSize = 108;
  469. } else {
  470. qustion = "[读 src='" + result[i].Word + "']" + json.CHN.PinYin[0].pinyin + "[/读]\n";
  471. answer = result[i].Word + "\n\n";
  472. if (json.CHN.KaitiArr) {
  473. for (let j = 0; j < json.CHN.KaitiArr.length; j++) {
  474. answer += "[图 w='650' h='650']" + json.CHN.KaitiArr[j] + "[/图]\n";
  475. }
  476. }
  477. answer += json.CHN.PinYin[0].explain;
  478. tags = "怎么写";
  479. }
  480. obj.Word = result[i].Word;
  481. obj.ReadString = result[i].Word;
  482. obj.Content = [];
  483. obj.Content.push({ContentType: 0, Content: tags});
  484. obj.Content.push({ContentType: 1, Content: qustion});
  485. obj.Content.push({ContentType: 2, Content: answer});
  486. obj.Content.push({ContentType: 3, Content: ""});
  487. arrTemp.push(obj);
  488. }
  489. temp = result[i].Word;
  490. }
  491. result = arrTemp;
  492. }
  493. }
  494. //文言文部分
  495. else if (unitInfo && unitInfo.length > 0 && unitInfo[0].UnitType == 4) {
  496. const words = await hanzi.GetHanziUnitByID(param);
  497. const arrAncientList = await hanzi.GetAncientChineseProse({IsList: 0});
  498. if (words[0] && words[0].Name) {
  499. result = [];
  500. for (let i = 0; i < arrAncientList.length; i++) {
  501. if (arrAncientList[i].Word == words[0].Name) {
  502. let qustion, answer, tags;
  503. qustion = arrAncientList[i].ExampleSentence;
  504. qustion = stringUtils.ReplaceAllString(qustion, arrAncientList[i].Word, "[光]" + arrAncientList[i].Word + "[/光]");
  505. const readString = "“" + arrAncientList[i].Word + "”字在这里的意思是" + arrAncientList[i].Definitions;
  506. answer = "[读 src='" + readString + "']" + arrAncientList[i].Definitions + "[/读]\n\n";
  507. if (arrAncientList[i].ExampleDefinitions.indexOf("译文") < 0)
  508. answer += "译文:";
  509. answer += arrAncientList[i].ExampleDefinitions;
  510. tags = "文言文字释义";
  511. const obj = {};
  512. obj.Word = "【" + arrAncientList[i].Word + "】" + arrAncientList[i].Definitions;
  513. obj.ReadString = readString;
  514. obj.Content = [];
  515. obj.Content.push({ContentType: 0, Content: tags});
  516. obj.Content.push({ContentType: 1, Content: qustion});
  517. obj.Content.push({ContentType: 2, Content: answer});
  518. obj.Content.push({ContentType: 3, Content: ""});
  519. result.push(obj);
  520. }
  521. }
  522. }
  523. }
  524. //小古文部分
  525. else if (unitInfo && unitInfo.length > 0 && unitInfo[0].UnitType == 3) {
  526. const words = await hanzi.GetHanziUnitByID(param);
  527. const resultList = await hanzi.GetAncientChineseProseSentence({Unit: words[0].Name});
  528. if (words[0] && words[0].Name) {
  529. result = [];
  530. for (let i = 0; i < resultList.length; i++) {
  531. let qustion, answer, tags;
  532. if (param.TestType == "read") {
  533. qustion = resultList[i].Question;
  534. answer = "[光]" + resultList[i].Sentence + "[/光]\n\n";
  535. answer += "含义\n• ";
  536. answer += resultList[i].Paraphrase + "\n\n";
  537. if (resultList[i].Explain) {
  538. answer += "详解\n• ";
  539. answer += resultList[i].Explain + "\n\n";
  540. }
  541. if (resultList[i].Idiom) {
  542. answer += "句中包含的成语\n• ";
  543. answer += resultList[i].Idiom + "\n\n";
  544. }
  545. if (resultList[i].SentenceFragment) {
  546. answer += "原文片段\n• ";
  547. answer += resultList[i].SentenceFragment + "\n\n";
  548. }
  549. if (resultList[i].Source) {
  550. answer += "出自\n• ";
  551. answer += "《" + resultList[i].Source + "》 ";
  552. if (resultList[i].Author)
  553. answer += resultList[i].Author + " ";
  554. if (resultList[i].Dynasty)
  555. answer += "(" + resultList[i].Dynasty + ")";
  556. answer += "\n\n";
  557. }
  558. tags = "接下文";
  559. } else {
  560. qustion = resultList[i].Paraphrase;
  561. answer = "[光]" + resultList[i].Sentence + "[/光]\n\n";
  562. if (resultList[i].Explain) {
  563. answer += "详解\n• ";
  564. answer += resultList[i].Explain + "\n\n";
  565. }
  566. if (resultList[i].Idiom) {
  567. answer += "句中包含的成语\n• ";
  568. answer += resultList[i].Idiom + "\n\n";
  569. }
  570. if (resultList[i].SentenceFragment) {
  571. answer += "原文片段\n• ";
  572. answer += resultList[i].SentenceFragment + "\n\n";
  573. }
  574. if (resultList[i].Source) {
  575. answer += "出自\n• ";
  576. answer += "《" + resultList[i].Source + "》 ";
  577. if (resultList[i].Author)
  578. answer += resultList[i].Author + " ";
  579. if (resultList[i].Dynasty)
  580. answer += "(" + resultList[i].Dynasty + ")";
  581. answer += "\n\n";
  582. }
  583. tags = "说古文";
  584. }
  585. const obj = {};
  586. obj.Word = resultList[i].Sentence;
  587. obj.Content = [];
  588. obj.Content.push({ContentType: 0, Content: tags});
  589. obj.Content.push({ContentType: 1, Content: qustion});
  590. obj.Content.push({ContentType: 2, Content: answer});
  591. obj.Content.push({ContentType: 3, Content: ""});
  592. result.push(obj);
  593. }
  594. }
  595. }
  596. globalCache.set("GetHanziUnitWords?UnitID=" + param.UnitID + "&TestType=" + param.TestType, result, config.BufferMemoryTimeHigh);
  597. }
  598. ctx.body = {"errcode": 10000, result: result};
  599. }
  600. //添加自定义汉字
  601. export async function AddHanziCustom(ctx) {
  602. const param = ctx.request.body;
  603. let userCustom = await hanzi.GetUsersUnitCustomList(param);
  604. if (userCustom && userCustom.length>0){
  605. await hanzi.UpdateHanziCustom(param);
  606. }
  607. else {
  608. await hanzi.AddHanziCustom(param);
  609. }
  610. ctx.body = {"errcode": 10000};
  611. }
  612. //得到自定义汉字列表
  613. export async function GetHanziCustomList(ctx) {
  614. const param = {
  615. UserID: ctx.query.UserID || 0,
  616. };
  617. if (param.UserID=="undefined")
  618. param.UserID=0;
  619. let result = await hanzi.GetHanziCustomList(param);
  620. if (result && result.length > 0) {
  621. for (let n = 0; n < result.length; n++) {
  622. result[n].List = result[n].UnitCustom;
  623. result[n].ID = result[n].UnitID;
  624. delete result[n].CreateTime;
  625. delete result[n].UnitCustom;
  626. delete result[n].UserID;
  627. delete result[n].UnitID;
  628. }
  629. ctx.body = {"errcode": 10000, result: result};
  630. }
  631. else
  632. ctx.body = {"errcode": 10000, result: []};
  633. }
  634. //得到测试汉字列表
  635. export async function GetHanziTestList(ctx) {
  636. const param = {
  637. Type: "random"
  638. };
  639. const result = await hanzi.GetHanziWords(param);
  640. if (result && result.length > 0) {
  641. let arr = [], arrChild = [];
  642. let temp = 0;
  643. for (let i = 0; i < result.length; i++) {
  644. if (temp > 0 && temp != result[i].HanziUnitID) {
  645. arr.push(arrChild);
  646. arrChild=[];
  647. }
  648. arrChild.push(result[i]);
  649. temp = result[i].HanziUnitID;
  650. }
  651. arr.push(arrChild);
  652. const arrResult = [];
  653. for (let i = 0; i < arr.length; i++) {
  654. //console.log(arr[i].length);
  655. const arrTemp = stringUtils.RandomArray(arr[i]);
  656. for (let j = 0; j < 3; j++) {
  657. //console.log(arrTemp[j].ID);
  658. if (arrTemp && arrTemp[j] && arrTemp[j].PinyinTest) {
  659. arrTemp[j].PinyinTest = JSON.parse(arrTemp[j].PinyinTest);
  660. const arr1 = [];
  661. if (arrTemp[j].PinyinTest.easy.length > 0) {
  662. arr1.push(arrTemp[j].PinyinTest.easy);
  663. arr1.push(arrTemp[j].PinyinTest.easy);
  664. }
  665. if (arrTemp[j].PinyinTest.normal.length > 0) {
  666. arr1.push(arrTemp[j].PinyinTest.normal);
  667. arr1.push(arrTemp[j].PinyinTest.normal);
  668. arr1.push(arrTemp[j].PinyinTest.normal);
  669. }
  670. const num = stringUtils.Random(0, arr1.length - 1);
  671. //if (arr1[num]==undefined) {
  672. // console.log(num);
  673. // console.log(arr1);
  674. //}
  675. const arr3 = arr1[num];
  676. const arr2 = [];
  677. if (arr3[0])
  678. arr2.push({ options: arr3[0] });
  679. if (arr3[1])
  680. arr2.push({ options: arr3[1] });
  681. if (arr3[2])
  682. arr2.push({ options: arr3[2] });
  683. arr2.push({ options: arrTemp[j].PinyinTest.answer, "IsAnswer": true });
  684. arrTemp[j].PinyinTest = stringUtils.RandomArray(arr2);
  685. arrResult.push(arrTemp[j]);
  686. }
  687. }
  688. }
  689. ctx.body = { errcode: 10000, result: arrResult };
  690. }
  691. else {
  692. ctx.body = { errcode: 10000, result: [] };
  693. }
  694. }
  695. //得到非课本汉字数据
  696. export async function SearchHanzi(ctx) {
  697. const param = {
  698. Word: ctx.query.Word,
  699. };
  700. const result = await hanzi.GetHanziWordsByWord(param);
  701. if (result && result.length > 0) {
  702. if (result[0].HasImage==0)
  703. buildHanziKaishu(param.Word);
  704. result[0].WordUrl="https://hanzi-1253256735.file.myqcloud.com/images/hanzi"+param.Word+".jpg";
  705. result[0].IsNew=false;
  706. ctx.body = {"errcode": 10000, result: result[0]};
  707. }
  708. else {
  709. const hanzi1 = encodeURI(param.Word);
  710. const url = "http://localhost:"+config.port+"/api/GetLiteracyData?Word=" + hanzi1;
  711. const result2 = await axios.get(url)
  712. .then(function (response) {
  713. const obj = response.data;
  714. const data = obj.result;
  715. const arrTemp = [];
  716. if (data.CombineWords && data.CombineWords.length>0)
  717. arrTemp.push(data.CombineWords[0]);
  718. let pinyin = "";
  719. for(let i=0; i<data.PinYin.length; i++){
  720. pinyin += "," + data.PinYin[i].pinyin;
  721. }
  722. if (pinyin)
  723. pinyin = pinyin.substring(1);
  724. const obj2 = {
  725. HanziUnitID: 0,
  726. Name: param.Word,
  727. Pinyin: pinyin,
  728. CombineWords: arrTemp.join(","),
  729. Details: JSON.stringify(data),
  730. };
  731. return obj2;
  732. });
  733. const insertID = await hanzi.AddHanziWord(result2);
  734. result2.ID = insertID.insertId;
  735. result2.IsNew = true;
  736. buildHanziKaishu(param.Word);
  737. result2.WordUrl = "https://hanzi-1253256735.file.myqcloud.com/images/hanzi"+param.Word+".jpg";
  738. ctx.body = {"errcode": 10000, result: result2};
  739. }
  740. // 生成汉字楷书图片并上传到腾讯云
  741. async function buildHanziKaishu(data) {
  742. try {
  743. const path = './public/images/';
  744. const imageUrl = path + 'hanziBg.png';
  745. const filepath = path + 'hanzi/hanzi.jpeg';
  746. // 确保目录存在
  747. await fsPromises.mkdir(path + 'hanzi', { recursive: true }).catch(() => {});
  748. // 生成汉字图片
  749. await new Promise((resolve, reject) => {
  750. imageMagick(imageUrl)
  751. .font(config.fontsPathKaiti, 366)
  752. .fill('#000000')
  753. .drawText(0, 290, data)
  754. .write(filepath, (err) => {
  755. if (err) reject(err);
  756. else resolve();
  757. });
  758. });
  759. // 上传图片到腾讯云
  760. await uploadHanziImage(data, filepath);
  761. } catch (error) {
  762. console.error('生成汉字图片失败:', error);
  763. }
  764. }
  765. // 上传汉字图片到腾讯云
  766. async function uploadHanziImage(data, filepath) {
  767. const timeStart = new Date();
  768. const cos = new COS(config.QCloud);
  769. try {
  770. // 检查文件是否存在
  771. await fsPromises.stat(filepath);
  772. const params = {
  773. Bucket: 'hanzi-1253256735',
  774. Region: 'ap-guangzhou',
  775. Key: 'images/hanzi' + data + '.jpg',
  776. Body: fs.createReadStream(filepath),
  777. ContentLength: fs.statSync(filepath).size
  778. };
  779. // 使用Promise包装COS上传
  780. await new Promise((resolve, reject) => {
  781. cos.putObject(params, (err, data) => {
  782. if (err) reject(err);
  783. else resolve(data);
  784. });
  785. });
  786. // 更新数据库中的汉字状态
  787. await hanzi.UpdateHanziWords({
  788. Name: data,
  789. HasImage: 1
  790. });
  791. const duration = (new Date().getTime() - timeStart.getTime());
  792. console.log(`汉字"${data}"图片上传完成,耗时: ${duration}ms`);
  793. } catch (error) {
  794. console.error(`上传汉字"${data}"图片失败:`, error);
  795. } finally {
  796. // 清理临时文件
  797. try {
  798. if (await fsPromises.stat(filepath).catch(() => false)) {
  799. await fsPromises.unlink(filepath);
  800. }
  801. } catch (e) {
  802. console.error('清理临时文件失败:', e);
  803. }
  804. }
  805. }
  806. }
  807. //得到用户记录
  808. export async function GetHanziRecordData(ctx) {
  809. const param = {
  810. UserID: ctx.query.UserID || 0,
  811. Version: ctx.query.Version || "1.0.0",
  812. };
  813. if (param.UserID=="undefined")
  814. param.UserID=0;
  815. const result = await hanzi.GetHanziRecordData(param);
  816. if (param.UserID>0 && result && result.length > 0) {
  817. const userList = await hanzi.GetUsersInfoByUserID(param);
  818. //是否是首日
  819. const timeCreateTime = moment(userList[0].CreateTime).format('YYYYMMDD');
  820. const timeToday = moment().format('YYYYMMDD');
  821. if (timeCreateTime==timeToday)
  822. result[0].IsFirstDay=true;
  823. else
  824. result[0].IsFirstDay=false;
  825. //得到分享新增用户数
  826. let productServiceTime = moment(userList[0].ProductServiceTime).format('YYYYMMDD');
  827. if (productServiceTime=="20991231"){
  828. result[0].NewUserNumber=999999;
  829. }
  830. else {
  831. const newUserNumber = await hanzi.GetNewUserByUserID(param);
  832. if (newUserNumber) {
  833. result[0].NewUserNumber = newUserNumber.length;
  834. //console.log("userList[0].ActivityTime:"+userList[0].ActivityTime);
  835. productServiceTime = moment(userList[0].ProductServiceTime).format('YYYYMMDD');
  836. const currentTime = moment().format('YYYYMMDD');
  837. //如果推荐用户数超过6个,就改为增加3个月
  838. if (newUserNumber.length>=6 && !userList[0].ActivityTime && productServiceTime>=currentTime){
  839. const obj={
  840. ActivityTime:moment().format('YYYY-MM-DD HH:mm:ss'),
  841. ProductServiceTime:moment(userList[0].ProductServiceTime).add(1, 'months').format('YYYY-MM-DD HH:mm:ss'),
  842. OpenID:userList[0].OpenID,
  843. }
  844. await hanzi.UpdateUsers(obj);
  845. result[0].NewUserNumber=999999;
  846. }
  847. }
  848. }
  849. result[0].IsMember=userList[0].IsMember;
  850. if (productServiceTime<timeToday)
  851. result[0].IsMember=0;
  852. //完成章节
  853. const result2 = await hanzi.GetHanziFinishedDataCount(param);
  854. if (result2)
  855. result[0].FinishedList=result2;
  856. //复习字
  857. const list2 = await hanzi.GetHanziReviewList(param);
  858. if (list2)
  859. result[0].ReviewList = list2;
  860. //产品支付是否显示
  861. const param2={
  862. ProgramID:106,
  863. Version:param.Version,
  864. };
  865. const result3 = await commonModel.GetProductVersionList(param2);
  866. if (result3) {
  867. if ((param.Version==result3[0].Version && result3[0].IsShowPay<=0)
  868. || param.Version>result3[0].Version){
  869. result[0].IsShow=result3[0].IsShowPay;
  870. }
  871. else{
  872. result[0].IsShow=1;
  873. }
  874. //针对iphone测试用户,永远是无支付状态
  875. if (userList[0].Brand=='iPhone' && userList[0].WXLanguage=='en-US'
  876. && userList[0].UserSource=='1001' && userList[0].IsPay==0){
  877. result[0].IsShow=0;
  878. }
  879. }
  880. if (!result[0].HanziNumber)
  881. result[0].HanziNumber=0;
  882. ctx.body = {"errcode": 10000, result: result[0]};
  883. }
  884. else
  885. ctx.body = {"errcode": 10000};
  886. }
  887. //新增识字复习记录
  888. export async function UpdateHanziReview(ctx) {
  889. const param = ctx.request.body;
  890. if (param.Status == "add") {
  891. delete param.Status;
  892. if (param.UserID && param.Word) {
  893. await hanzi.AddHanziReview(param);
  894. }
  895. }
  896. else if (param.Status == "deleteAll") {
  897. delete param.Status;
  898. if (param.UserID) {
  899. await hanzi.DeleteHanziReviewAll(param);
  900. }
  901. }
  902. else if (param.Status == "delete") {
  903. delete param.Status;
  904. if (param.UserID && param.Word) {
  905. await hanzi.DeleteHanziReview(param);
  906. }
  907. }
  908. const result = await hanzi.GetHanziReviewList(param);
  909. if (result && result.length > 0)
  910. ctx.body = {"errcode": 10000, result: result};
  911. else
  912. ctx.body = {"errcode": 10000, result: []};
  913. }
  914. //得到用户完成记录
  915. export async function GetHanziReviewList(ctx) {
  916. const param = {
  917. UserID: ctx.query.UserID || 0,
  918. };
  919. if (param.UserID=="undefined")
  920. param.UserID=0;
  921. const result = await hanzi.GetHanziReviewList(param);
  922. if (result && result.length > 0)
  923. ctx.body = {"errcode": 10000, result: result};
  924. else
  925. ctx.body = {"errcode": 10000, result: []};
  926. }
  927. //得到用户邀请新用户列表
  928. export async function GetHanziUserListByIntroducer(ctx) {
  929. const param = {
  930. UserID: ctx.query.UserID || 0,
  931. };
  932. if (param.UserID=="undefined")
  933. param.UserID=0;
  934. const result = await hanzi.GetNewUserByUserID(param);
  935. if (result && result.length > 0) {
  936. ctx.body = {"errcode": 10000, result: result};
  937. }
  938. else
  939. ctx.body = {"errcode": 10000, result: []};
  940. }
  941. //得到单元汉字列表
  942. export async function GetHanziWordListByUnitID(ctx) {
  943. const param = {
  944. UserID: ctx.query.UserID || 0,
  945. UnitID: ctx.query.UnitID || 0,
  946. Type: "all",
  947. };
  948. if (param.UserID == "undefined")
  949. param.UserID = 0;
  950. const result = await hanzi.GetHanziWords(param);
  951. const userCustom = await hanzi.GetUsersUnitCustomList(param);
  952. let list = [];
  953. if (userCustom && userCustom.length > 0 && userCustom[0].UnitCustom) {
  954. //console.log(userCustom[0].UnitCustom);
  955. list = JSON.parse(userCustom[0].UnitCustom);
  956. }
  957. if (result && result.length > 0) {
  958. for (let i = 0; i < result.length; i++) {
  959. const item = result[i];
  960. item.Details = JSON.parse(item.Details);
  961. const CombineWordsOther = item.Details.CombineWords;
  962. const other = [];
  963. const main = item.CombineWords.split(",");
  964. for (let j = 0; j < CombineWordsOther.length; j++) {
  965. let b = true;
  966. for (let k = 0; k < main.length; k++) {
  967. if (CombineWordsOther[j] == main[k]) {
  968. b = false;
  969. break;
  970. }
  971. }
  972. if (b)
  973. other.push(CombineWordsOther[j]);
  974. }
  975. item.CombineWords = [];
  976. if (list.length > 0) {
  977. //console.log(list);
  978. for (let n = 0; n < main.length; n++) {
  979. let obj = {
  980. css: "",
  981. name: main[n],
  982. }
  983. for (let k = 0; k < list.length; k++) {
  984. if (list[k].Name == item.Name) {
  985. list[k].CombineWords = "," + list[k].CombineWords;
  986. if (list[k].CombineWords.indexOf("," + main[n]) >= 0) {
  987. //console.log(list[k].CombineWords);
  988. //console.log(main[n]);
  989. obj.css = "selected";
  990. break;
  991. }
  992. }
  993. }
  994. item.CombineWords.push(obj);
  995. }
  996. for (let n = 0; n < other.length; n++) {
  997. let obj = {
  998. css: "",
  999. name: other[n],
  1000. }
  1001. for (let k = 0; k < list.length; k++) {
  1002. if (list[k].Name == item.Name) {
  1003. list[k].CombineWords = "," + list[k].CombineWords;
  1004. if (list[k].CombineWords.indexOf("," + other[n]) >= 0) {
  1005. obj.css = "selected";
  1006. break;
  1007. }
  1008. }
  1009. }
  1010. item.CombineWords.push(obj);
  1011. }
  1012. }
  1013. else {
  1014. for (let n = 0; n < main.length; n++) {
  1015. let obj = {
  1016. css: "selected",
  1017. name: main[n],
  1018. }
  1019. item.CombineWords.push(obj);
  1020. }
  1021. for (let n = 0; n < other.length; n++) {
  1022. let obj = {
  1023. css: "",
  1024. name: other[n],
  1025. }
  1026. item.CombineWords.push(obj);
  1027. }
  1028. }
  1029. //console.log(item.Pinyin);
  1030. //console.log(item.CombineWords);
  1031. delete item.Details;
  1032. delete item.HanziUnitID;
  1033. delete item.HasImage;
  1034. }
  1035. ctx.body = { "errcode": 10000, result: result };
  1036. }
  1037. else
  1038. ctx.body = { "errcode": 10000, result: [] };
  1039. }