feat: 添加选项题

This commit is contained in:
zyronon
2025-05-22 03:02:23 +08:00
parent 4146a6e5eb
commit 444c11e717
30 changed files with 2718 additions and 2205 deletions

5
TODO.md Normal file
View File

@@ -0,0 +1,5 @@
nce1-16.A polite request.解析出来有问题
I found this note on my car: 'Sir, we welcome you to our city. This is a 'No Parking' area. You will enjoy your stay here if you pay attention to our street signs. This note is only a reminder.' If you receive a request like this, you cannot fail to obey it!
'No Parking' 会被截断

2
components.d.ts vendored
View File

@@ -14,6 +14,8 @@ declare module 'vue' {
DeleteIcon: typeof import('./src/components/icon/DeleteIcon.vue')['default']
ElButton: typeof import('element-plus/es')['ElButton']
ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
ElCollapse: typeof import('element-plus/es')['ElCollapse']
ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem']
ElForm: typeof import('element-plus/es')['ElForm']
ElFormItem: typeof import('element-plus/es')['ElFormItem']
ElInput: typeof import('element-plus/es')['ElInput']

View File

@@ -15,58 +15,58 @@
"i18n:write": "gulp i18nwrite"
},
"dependencies": {
"@imengyu/vue3-context-menu": "^1.4.5",
"@imengyu/vue3-context-menu": "^1.5.0",
"@opentranslate/baidu": "^1.4.2",
"@opentranslate/translator": "^1.4.2",
"axios": "^1.7.2",
"compromise": "^14.10.0",
"axios": "^1.9.0",
"compromise": "^14.14.4",
"copy-to-clipboard": "^3.3.3",
"dayjs": "^1.11.11",
"element-plus": "^2.9.7",
"dayjs": "^1.11.13",
"element-plus": "^2.9.10",
"file-saver": "^2.0.5",
"git-last-commit": "^1.0.1",
"hover.css": "^2.3.2",
"jquery": "^3.7.1",
"libarchive-wasm": "^1.1.0",
"libarchive-wasm": "^1.2.0",
"localforage": "^1.10.0",
"lodash-es": "^4.17.21",
"mitt": "^3.0.1",
"nanoid": "^5.0.3",
"pinia": "^2.1.6",
"sentence-splitter": "^4.2.1",
"nanoid": "^5.1.5",
"pinia": "^2.3.1",
"sentence-splitter": "^4.4.1",
"string-comparison": "^1.3.0",
"tesseract.js": "^4.1.1",
"vant": "^4.8.1",
"vue": "^3.4.27",
"tesseract.js": "^4.1.4",
"vant": "^4.9.19",
"vue": "^3.5.14",
"vue-activity-calendar": "^1.2.2",
"vue-i18n": "9",
"vue-router": "4",
"vue-toast-notification": "3",
"vue-i18n": "^9.14.4",
"vue-router": "^4.5.1",
"vue-toast-notification": "^3.1.3",
"vue-virtual-scroller": "2.0.0-beta.8"
},
"devDependencies": {
"@iconify/vue": "^4.1.1",
"@types/file-saver": "^2.0.5",
"@types/lodash-es": "^4.17.9",
"@unocss/postcss": "^0.60.2",
"@vitejs/plugin-vue": "^4.2.3",
"@vitejs/plugin-vue-jsx": "^3.0.1",
"@vue/compiler-sfc": "^3.3.4",
"commitizen": "^4.3.0",
"@iconify/vue": "^4.3.0",
"@types/file-saver": "^2.0.7",
"@types/lodash-es": "^4.17.12",
"@unocss/postcss": "^0.60.4",
"@vitejs/plugin-vue": "^4.6.2",
"@vitejs/plugin-vue-jsx": "^3.1.0",
"@vue/compiler-sfc": "^3.5.14",
"commitizen": "^4.3.1",
"cz-conventional-changelog": "^3.3.0",
"esm": "^3.2.25",
"gulp": "^4.0.2",
"husky": "^8.0.3",
"rollup-plugin-visualizer": "^5.9.2",
"sass": "^1.64.2",
"tslib": "^2.6.2",
"typescript": "^5.2.0",
"unocss": "^0.60.2",
"unplugin-auto-import": "^0.16.6",
"rollup-plugin-visualizer": "^5.14.0",
"sass": "^1.89.0",
"tslib": "^2.8.1",
"typescript": "^5.8.3",
"unocss": "^0.60.4",
"unplugin-auto-import": "^0.16.7",
"unplugin-vue-components": "^0.25.2",
"unplugin-vue-macros": "^2.9.3",
"vite": "^5.2.11",
"vue-tsc": "^2.0.19",
"unplugin-vue-macros": "^2.14.5",
"vite": "^5.4.19",
"vue-tsc": "^2.2.10",
"xlsx": "^0.18.5"
},
"config": {

4017
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -115,7 +115,7 @@
"id": "D_fWgW",
"title": "Goodbye and good luck",
"titleTranslate": "再见, 一路顺风",
"text": "Our neighbour, Captain Charles Alison, will sail from Portsmouth tomorrow. Well meet him at the harbour early in the morning. He will be in his small boat, Topsail. Topsail is a famous little boat. It has sailed across the Atlantic many times. Captain Alison will set out at eight oclock, so well have plenty of time. Well see his boat and then well say goodbye to him. He will be away for two months. We are very proud of him. He will take part in an important race across the Atlantic.",
"text": "Our neighbour, Captain Charles Alison, will sail from Portsmouth tomorrow. We'll meet him at the harbour early in the morning. He will be in his small boat, Topsail. Topsail is a famous little boat. It has sailed across the Atlantic many times. Captain Alison will set out at eight o'clock, so we'll have plenty of time. We'll see his boat and then we'll say goodbye to him. He will be away for two months. We are very proud of him. He will take part in an important race across the Atlantic.",
"textTranslate": "我们的邻居查尔斯.艾利森船长明天就要从朴次茅斯启航了。\n明天一大早我们将在码头为他送行。\n他将乘坐他的“涛波赛”号小艇。\n“涛波赛”号是艘有名的小艇\n它已经多次横渡大西洋。\n艾利森船长将于8点钟启航因此我们有充裕的时间。\n我们将参观他的船然后和他告别。\n他要离开两个月\n我们真为他感到自豪\n他将参加一次重大的横渡大西洋的比赛。",
"newWords": [],
"textAllWords": [],
@@ -127,44 +127,44 @@
"title": "The Greenwood Boys",
"titleTranslate": "绿林少年",
"text": "The Greenwood Boys are a group of pop singers. At present, they are visiting all parts of the country. They will be arriving here tomorrow. They will be coming by train and most of the young people in the town will be meeting them at the station. Tomorrow evening they will be singing at the Workers Club. The Greenwood Boys will be staying for five days. During this time, they will give five performances. As usual, the police will have a difficult time. They will be trying to keep order. It is always the same on these occasions.",
"textTranslate": "格林伍德男孩是一流行歌。\n目前他们正在访问全国各地。\n他们明天将到达这里。\n他们将乘火车来镇上的大多数年轻人将车站迎接他们。\n明晚他们将在工人俱乐部唱歌。\n格林伍德男孩将在这里呆五天。\n在此期间他们将进行五场演出。\n往常一样,警察会遇到困难。\n他们将努力维持秩序。\n在这些场合总是一样。",
"textTranslate": "“绿林少年”是一流行歌曲演唱团。\n目前他们正在全国各地巡回演出,\n明天就要到达此地。\n他们将乘火车来镇上的大部分青年人将车站迎接他们。\n明晚他们将在工人俱乐部演出。\n“绿林少年”准备在此逗留5天。\n在此期间他们将演出5场。\n往常一样,警察的日子将不好过,\n他们将设法维持秩序。\n每逢这种场合,情况都是这样。",
"newWords": [],
"textAllWords": [],
"audioSrc": "/public/sound/article/nce2-1/12Goodbye and Good Luck.mp3",
"lrcPosition": []
"audioSrc": "/public/sound/article/nce2-1/13The Greenwood Boys.mp3",
"lrcPosition": [[15.28,19.38],[19.38,24.48],[24.48,27.76],[27.76,35.81],[35.81,40.82],[40.82,45.24],[45.24,50.16],[50.16,54.7],[54.7,57.56],[57.56,-1]]
},
{
"id": "iD9wWE",
"title": "Do you speak English?",
"titleTranslate": "你会讲英语吗?",
"text": "I had an amusing experience last year. After I had left a small village in the south of France, I drove on to the next town. On the way, a young man waved to me. I stopped and he asked me for a lift. As soon as he had got into the car, I said good morning to him in French and he replied in the same language. Apart from a few words, I do not know any French at all. Neither of us spoke during the journey. I had nearly reached the town, when the young man suddenly said, very slowly, \"Do you speak English? As I soon learnt, he was English himself!",
"textTranslate": "去年我有一次有趣的经历。\n离开法国南部的一个小村庄后驱车前往下一个城镇。\n在路上,一个年人向我手。\n我停下,他让我搭便车。\n他一上车我就用法语和他说早上好,他也同样的语言回答。\n除了几个字,我一点法语都不懂。\n旅途中我们俩都没说话。\n我快到城里的时候年轻人突然很慢地说:“你会英语吗?\n我很快就知道了,他自己就是英国人!",
"text": "I had an amusing experience last year. After I had left a small village in the south of France, I drove on to the next town. On the way, a young man waved to me. I stopped and he asked me for a lift. As soon as he had got into the car, I said good morning to him in French and he replied in the same language. Apart from a few words, I do not know any French at all. Neither of us spoke during the journey. I had nearly reached the town, when the young man suddenly said, very slowly, 'Do you speak English?' As I soon learnt, he was English himself!",
"textTranslate": "去年我有一次有趣的经历。\n离开法国南部的一个小村庄后,我继续驶往下一个城镇。\n途中,一个年人向我手。\n我把车停下,他向我提出要求搭车。\n他一上车我就用法语向他问早上好,他也同样用法语回答。\n除了个别几个单词外,我根本不会法语。\n旅途中我们谁也没讲话。\n就要到达那个镇时那青年突然开了口慢地说:“你会英语吗?\n我很快了解到,他自己就是英国人!",
"newWords": [],
"textAllWords": [],
"audioSrc": "/public/sound/article/nce2-1/12Goodbye and Good Luck.mp3",
"lrcPosition": []
"audioSrc": "/public/sound/article/nce2-1/14Do You Speak English.mp3",
"lrcPosition": [[15.27,19.24],[19.24,26.04],[26.82,30.58],[30.58,34.62],[34.62,43.9],[43.9,49.7],[50.17,53.32],[53.32,64.17],[64.63,68.7]]
},
{
"id": "w4ytao",
"title": "Good news",
"titleTranslate": "佳音",
"text": "The secretary told me that Mr. Harmsworth would see me. I felt very nervous when I went into his office. He did not look up from his desk when I entered. After I had sat down, he said that business was very bad. He told me that the firm could not afford to pay such large salaries. Twenty people had already left. I knew that my turn had come.\nMr.Harmsworth, I said in a weak voice.\nDon't interrupt, he said.\nThen he smiled and told me I would receive an extra thousand pounds a year!",
"textTranslate": "秘书告诉我说哈姆斯沃斯先生要见我。\r\n我走进他的办公室感到非常紧张。\r\n我进去的时候他连头也没抬。\r\n待我坐下后他说生意非常不景气。\r\n他还告诉我公司支付不起这么庞大的工资开支\r\n有20个人已经离去。\r\n我知道这次该轮到我了。\r\n\r\n“哈姆斯沃斯先生”我无力地说。\r\n\r\n“不要打断我的话”他说。\r\n\r\n然后他微笑了一下告诉我说我每年将得到1,000 英镑的额外收入。",
"text": "The secretary told me that Mr. Harmsworth would see me.\nI felt very nervous when I went into his office.\nHe did not look up from his desk when I entered.\nAfter I had sat down, he said that business was very bad.\nHe told me that the firm could not afford to pay such large salaries.\nTwenty people had already left.\nI knew that my turn had come.\n\n'Mr.Harmsworth,' I said in a weak voice.\n\n'Don't interrupt,' he said.\n\nThen he smiled and told me I would receive an extra thousand pounds a year!",
"textTranslate": " 秘书告诉我说哈姆斯沃斯先生要见我。\n我走进他的办公室感到非常紧张。\n我进去的时候他连头也没抬。\n待我坐下后他说生意非常不景气。\n他还告诉我公司支付不起这么庞大的工资开支\n有20个人已经离去。\n我知道这次该轮到我了。\n\n“哈姆斯沃斯先生”我无力地说。\n\n“不要打断我的话”他说。\n\n然后他微笑了一下告诉我说我每年将得到1,000 英镑的额外收入。",
"newWords": [],
"textAllWords": [],
"audioSrc": "/public/sound/article/nce2-1/12Goodbye and Good Luck.mp3",
"lrcPosition": []
"audioSrc": "/public/sound/article/nce2-1/15Good News.mp3",
"lrcPosition": [[13.88,19.28],[19.28,24.36],[24.36,28.84],[28.84,34.47],[35.1,41.52],[41.52,45.06],[45.06,48.59],[48.59,53.3],[53.3,56.14],[56.14,62.94]]
},
{
"id": "xRtmjP",
"title": "A polite request",
"titleTranslate": "彬彬有礼的要求",
"text": "If you park your car in the wrong place, a traffic policeman will soon find it. You will be very lucky if he lets you go without a ticket. However, this does not always happen. Traffic police are sometimes very polite. During a holiday in Sweden, I found this note on my car: sir, we welcome you to our city. This is a \"No Parking\" area. You will enjoy your stay here if you pay attention to our street signs. This note is only a reminder. If you receive a request like this, you cannot fail to obey it!",
"textTranslate": "一旦你把汽车停错了地方,交通警很快就会发现。\n如果他没给你罚单就放你走了算你走运。\n然而情况并不都是这样\n交通警有时也很客气。\n有一次在瑞典度假我发现我的车上有这样一个字条“先生欢迎您光临我们的城市。\n此处是禁止停车区。\n如果您对我们街上的标牌稍加注意您在此会过得很愉快的。\n谨此提请注意。\n如果你收到这样的恳求你是不会不遵照执行的",
"text": "If you park your car in the wrong place, a traffic policeman will soon find it.\nYou will be very lucky if he lets you go without a ticket.\nHowever, this does not always happen.\nTraffic police are sometimes very polite.\nDuring a holiday in Sweden,\nI found this note on my car: 'Sir, we welcome you to our city.\nThis is a \"No Parking\" area.\nYou will enjoy your stay here if you pay attention to our street signs. This note is only a reminder.'\nIf you receive a request like this, you cannot fail to obey it!",
"textTranslate": "一旦你把汽车停错了地方,交通警很快就会发现。\n如果他没给你罚单就放你走了算你走运。\n然而情况并不都是这样\n交通警有时也很客气。\n有一次在瑞典度假\n我发现我的车上有这样一个字条:“先生,欢迎您光临我们的城市。\n此处是禁止停车区。\n如果您对我们街上的标牌稍加注意您在此会过得很愉快的。谨此提请注意。\n如果你收到这样的恳求你是不会不遵照执行的",
"newWords": [],
"textAllWords": [],
"audioSrc": "/public/sound/article/nce2-1/12Goodbye and Good Luck.mp3",
"lrcPosition": []
"audioSrc": "/public/sound/article/nce2-1/16A Polite Request.mp3",
"lrcPosition": [[14.35,21.44],[21.68,26.86],[26.86,31.48],[31.48,35.98],[35.98,46.16],[46.76,49.52],[49.85,60.31],[60.31,66.95]]
},
{
"id": "Re_Cu3",
@@ -174,61 +174,63 @@
"textTranslate": "我的姑姑詹妮弗是位演员,\n她至少也有35岁了。\n尽管如此她却常在舞台上扮演小姑娘。\n詹妮弗很快又要参加一个新剧的演出。\n这一次她将扮演一个17岁的少女。\n演出时她必须穿一条鲜红色的裙子和黑色的长筒袜。\n去年在演另一个剧时她不得不穿短袜和一件鲜艳的橘红色的衣服。\n一旦有人问起她有多大年纪她总是回答“亲爱的长成大人真可怕啊”",
"newWords": [],
"textAllWords": [],
"audioSrc": "/public/sound/article/nce2-1/12Goodbye and Good Luck.mp3",
"lrcPosition": []
"audioSrc": "/public/sound/article/nce2-1/17Always Young.mp3",
"lrcPosition": [[17.39,20.95],[20.95,25.21],[25.21,31.68],[31.68,36.1],[36.1,41.18],[41.18,48.78],[48.78,57.45],[57.45,69.7]]
},
{
"id": "HA1xuj",
"title": "He often does this!",
"titleTranslate": "他经常干这种事!",
"text": "After I had had lunch at a village pub, I looked for my bag. I had left it on a chair beside the door and now it wasnt there! As I was looking for it, the landlord came in.\nDid you have a good meal?\" he asked.\nYes, thank you, I answered, but I cant pay the bill. I havent got my bag.\nThe landlord smiled and immediately went out. In a few minutes he returned with my bag and gave it back to me.\nIm very sorry, he said. My dog had taken it into the garden. He often does this!",
"textTranslate": "我在一家乡村小酒店吃过午饭后,就找我的提包。\n我曾把它放在门边的椅子上可这会儿不见了\n当我正在寻找时酒店老板走了进来。\n\n“您吃得好吗” 他问。\n\n“很好谢谢。” 我回答,但我付不了帐,\n我的提包没有了。”\n\n酒店老板笑了笑马上走了出去。\n一会儿工夫他拿着我的提包回来了把它还给了我。\n\n“实在抱歉”他说\n“我的狗把它弄到花园里去了\n他常干这种事!”",
"text": "After I had had lunch at a village pub, I looked for my bag.\nI had left it on a chair beside the door and now it wasn't there!\nAs I was looking for it, the landlord came in.\n\n'Did you have a good meal?' he asked.\n\n'Yes, thank you,' I answered,\n'but I can't pay the bill. I haven't got my bag.'\n\nThe landlord smiled and immediately went out.\nIn a few minutes he returned with my bag and gave it back to me.\n\n'I'm very sorry,' he said.\n'My dog had taken it into the garden.\nHe often does this!'",
"textTranslate": "我在一家乡村小酒店吃过午饭后,就找我的提包。\n我曾把它放在门边的椅子上可这会儿不见了\n当我正在寻找时酒店老板走了进来。\n\n“您吃得好吗” 他问。\n\n“很好谢谢。” 我回答,\n但我付不了帐,我的提包没有了。”\n\n酒店老板笑了笑马上走了出去。\n一会儿工夫他拿着我的提包回来了把它还给了我。\n\n“实在抱歉”他说\n“我的狗把它弄到花园里去了他常干这种事”",
"newWords": [],
"textAllWords": [],
"audioSrc": "/public/sound/article/nce2-1/12Goodbye and Good Luck.mp3",
"lrcPosition": []
"audioSrc": "/public/sound/article/nce2-1/18He Often does This.mp3",
"lrcPosition": [[14.28,20.98],[20.98,27.45],[27.45,32.45],[32.45,35.94],[35.94,38.86],[38.86,43.74],[44.3,48.8],[48.8,54.93],[54.93,57.74],[58.34,64],[62,63.9]]
},
{
"id": "fRow_v",
"title": "Sold out",
"titleTranslate": "票已售完",
"text": "'The play may begin at any moment,' I said.\n\n'It may have begun already,' Susan answered.\n\nI hurried to the ticket office. 'May I have two tickets please?' I asked.\n\n'I'm sorry, we've sold out,' the girl said.\n\n'What a pity!' Susan exclaimed.\n\nJust then, a man hurried to the ticket office.\n\n'Can I return these two tickets?' he asked.\n\n'Certainly,' the girl said.\n\nI went back to the ticket office at once.\n\n'Could I have those two tickets please?' I asked.\n\n'Certainly,' the girl said, 'but they're for next Wednesday's performance. Do you still want them?'\n\n'I might as well have them,' I said sadly.",
"textTranslate": "“剧马上就要开演了,”我说。\n\n“也许已经开演了呢”苏珊回答说。\n\n我匆匆赶到售票处\n问“我可以买两张票吗”\n\n“对不起票已售完。”那位姑娘说。\n\n“真可惜”苏珊大声说。\n\n正在这时一个男子匆匆奔向售票处。\n\n“我可以退掉这两张票吗”他问。\n\n“当然可以”那姑娘说。\n\n我马上又回到售票处。\n\n“我可以买那两张票吗”我问。\n\n“当然可以不过这两张票是下星期三的您是否还要呢”\n\n\n“我还是买下的好,”我垂头丧气地说。",
"textTranslate": "“剧马上就要开演了,”我说。\n\n“也许已经开演了呢”苏珊回答说。\n\n我匆匆赶到售票处\n问“我可以买两张票吗”\n\n“对不起票已售完。”那位姑娘说。\n\n“真可惜”苏珊大声说。\n\n正在这时一个男子匆匆奔向售票处。\n\n“我可以退掉这两张票吗”他问。\n\n“当然可以”那姑娘说。\n\n我马上又回到售票处。\n\n“我可以买那两张票吗”我问。\n\n“当然可以不过这两张票是下星期三的您是否还要呢”\n\n“我还是买下的好”我垂头丧气地说。",
"newWords": [],
"textAllWords": [],
"audioSrc": "/public/sound/article/nce2-1/12Goodbye and Good Luck.mp3",
"lrcPosition": []
"audioSrc": "/public/sound/article/nce2-1/19Sold out.mp3",
"lrcPosition": [[15.14,19.47],[19.47,24.55],[24.55,27.78],[27.78,32.35],[32.35,37.1],[37.1,41.51],[41.51,46.59],[46.59,51.15],[51.15,55.05],[55.05,59.44],[59.44,64.67],[65.27,74.86],[75.35,80.21]]
},
{
"id": "KKK8Wt",
"title": "One man in a boat",
"titleTranslate": "独坐孤舟",
"text": "Fishing is my favourite sport. I often fish for hours without catching anything. But this does not worry me. Some fishermen are unlucky. Instead of catching fish, they catch old boots and rubbish. I am even less lucky. I never catch anything -- not even old boots. After having spent whole mornings on the river, I always go home with an empty bag. You must give up fishing! my friends say. Its a waste of time. But they dont realize one important thing. Im not really interested in fishing. I am only interested in sitting in a boat and doing nothing at all!",
"text": "Fishing is my favourite sport. I often fish for hours without catching anything. But this does not worry me. Some fishermen are unlucky. Instead of catching fish, they catch old boots and rubbish. I am even less lucky. I never catch anything -- not even old boots. After having spent whole mornings on the river, I always go home with an empty bag. 'You must give up fishing!' my friends say. 'It's a waste of time.' But they don't realize one important thing. I'm not really interested in fishing. I am only interested in sitting in a boat and doing nothing at all!",
"textTranslate": "钓鱼是我特别喜爱的一项运动。\n我经常一钓数小时却一无所获\n但我从不为此烦恼。\n有些垂钓者就是不走运\n他们往往鱼钓不到却钓上来些旧靴子和垃圾。\n我的运气甚至还不及他们。\n我什么东西也未钓到过 -- 就连旧靴子也没有。\n我总是在河上呆上整整一上午然后空着袋子回家。\n“你可别再钓鱼了”\n我的朋友们说\n“这是浪费时间。”\n然而他们没有认识到重要的一点\n我并不是真的对钓鱼有兴趣\n我感兴趣的只是独坐孤舟无所事事",
"newWords": [],
"textAllWords": [],
"audioSrc": "/public/sound/article/nce2-1/12Goodbye and Good Luck.mp3",
"lrcPosition": []
"audioSrc": "/public/sound/article/nce2-1/20One man in a boat.mp3",
"lrcPosition": [[15.9,18.88],[18.88,24.11],[24.11,27.65],[27.65,30.69],[30.69,36.66],[37.33,40.24],[40.24,45.75],[46.45,54.28],[54.98,57.95],[57.65,59.01],[59.41,61.95],[62.5,67.05],[67.05,70.78],[70.78,76.58]]
},
{
"id": "4dUIAd",
"title": "Mad or not?",
"titleTranslate": "是不是疯了",
"text": "Aeroplanes are slowly driving me mad. I live near an airport and passing planes can be heard night and day. The airport was built years ago, but for some reason it could not be used then. Last year, however, it came into use. Over a hundred people must have been driven away from their homes by the noise. I am one of the few people left. Sometimes I think this house will be knocked down by a passing plane. I have been offered a large sum of money to go away, but I am determined to stay here. Everybody says I must be mad and they are probably right.",
"textTranslate": "飞机正在逐渐把我逼疯。\n我住在一个机场附近过往飞机日夜不绝于耳。\n机场是许多年前建的但由于某种原因当时未能启用。\n然而去年机场开始使用了。\n有100多人肯定是被噪音逼得已经弃家远去\n我是少数留下来的人中的一个。\n有时我觉得这房子就要被一架飞过的飞机撞倒。\n他们曾向我提供一大笔钱让我搬走但我决定留在这儿。\n大家都说我肯定是疯了也许他们说的是对的。",
"textTranslate": "飞机正在逐渐把我逼疯。\n我住在一个机场附近过往飞机日夜不绝于耳。\n机场是许多年前建的\n但由于某种原因当时未能启用。\n然而去年机场开始使用了。\n有100多人肯定是被噪音逼得已经弃家远去\n我是少数留下来的人中的一个。\n有时我觉得这房子就要被一架飞过的飞机撞倒。\n他们曾向我提供一大笔钱让我搬走\n但我决定留在这儿。\n大家都说我肯定是疯了也许他们说的是对的。",
"newWords": [],
"textAllWords": [],
"audioSrc": "/public/sound/article/nce2-1/12Goodbye and Good Luck.mp3",
"lrcPosition": []
"audioSrc": "/public/sound/article/nce2-1/21Mad or not.mp3",
"lrcPosition": [[15.83,20.58],[20.58,27.2],[27.2,30.18],[30.18,34.72],[34.93,39.66],[39.66,46.47],[46.47,50.39],[50.39,57.24],[57.24,62.07],[62.17,65.16],[65.82,71.27]]
},
{
"id": "OZ2pV9",
"title": "A glass envelope",
"titleTranslate": "玻璃信封",
"text": "My daughter, Jane, never dreamed of receiving a letter from a girl of her own age in Holland. Last year, we were travelling across the Channel and Jane put a piece of paper with her name and address on it into a bottle. She threw the bottle into the sea. She never thought of it again, but ten months later, she received a letter from a girl in Holland. Both girls write to each other regularly now. However, they have decided to use the post office. Letters will cost a little more, but they will certainly travel faster.",
"textTranslate": "我的女儿简从未想过会接到荷兰一位同龄姑娘的来信。\n去年当我们横渡英吉利海峡时简把写有她姓名和住址的一张纸条装进了一只瓶子\n又将瓶子扔进了大海。\n此后她就再没去想那只瓶子。但10个月以后她收到了荷兰一位姑娘的来信。\n现在这两位姑娘定期通信了。\n然而她们还是决定利用邮局。\n这样会稍微多花点钱但肯定是快得多了。",
"textTranslate": "我的女儿简从未想过会接到荷兰一位同龄姑娘的来信。\n去年当我们横渡英吉利海峡时简把写有她姓名和住址的一张纸条装进了一只瓶子\n又将瓶子扔进了大海。\n此后她就再没去想那只瓶子。\n但10个月以后她收到了荷兰一位姑娘的来信。\n现在这两位姑娘定期通信了。\n然而她们还是决定利用邮局。\n这样会稍微多花点钱但肯定是快得多了。",
"newWords": [],
"textAllWords": []
"textAllWords": [],
"audioSrc": "/public/sound/article/nce2-1/22A glass envelope.mp3",
"lrcPosition": [[16.79,26.87],[26.87,37.71],[37.71,41.19],[41.19,43.75],[43.75,49.93],[49.93,54.19],[54.19,59.72],[59.72,65.8]]
},
{
"id": "bmcYhE",
@@ -238,21 +240,22 @@
"textTranslate": "昨天我收到了姐姐的一封信,\n她住在尼日利亚。\n在信中她说她明年将到英国来。\n如果她来了她会感到非常惊奇了。\n我们现在住在乡间的一栋漂亮的新住宅里。\n这栋房子在我姐姐离开之前就已动工了\n是在5个月以前竣工的。\n我在信中告诉她她可以和我们住在一起。\n这栋房子里有许多房间还有一个漂亮的花园。\n它是一栋非常现代化的住宅因此在有些人看来很古怪。\n它肯定是这个地区唯一的一栋现代化住宅。",
"newWords": [],
"textAllWords": [],
"audioSrc": "/public/sound/article/nce2-1/12Goodbye and Good Luck.mp3",
"lrcPosition": []
"audioSrc": "/public/sound/article/nce2-1/23A new house.mp3",
"lrcPosition": [[15.29,19.23],[19.23,22.23],[22.23,28.38],[28.38,32.58],[32.58,37.85],[37.85,42.58],[42.58,46.5],[46.5,51.52],[51.52,57.35],[57.35,63.69],[63.69,68.19]]
},
{
"id": "cD1704",
"title": "It could be worse",
"titleTranslate": "不幸中之万幸",
"text": "I entered the hotel managers office and sat down. I had just lost $50 and I felt very upset. I left the money in my room, I said, and its not there now. The manager was sympathetic, but he could do nothing. Everyones losing money these days, he said. He started to complain about this wicked world but was interrupted by a knock at the door. A girl came in and put an envelope on his desk. It contained $50. I found this outside this gentlemans room, she said. Well, I said to the manager, there is still some honesty in this world!",
"text": "I entered the hotel manager's office and sat down. I had just lost $50 and I felt very upset. 'I left the money in my room,' I said, 'and it's not there now.' The manager was sympathetic, but he could do nothing. 'Everyone's losing money these days,' he said. He started to complain about this wicked world but was interrupted by a knock at the door. A girl came in and put an envelope on his desk. It contained $50. 'I found this outside this gentleman's room,' she said. 'Well,' I said to the manager, 'there is still some honesty in this world!'",
"textTranslate": "我走进饭店经理的办公室,坐了下来。\n我刚刚丢了50英镑感到非常烦恼。\n“我把钱放在房间里”我说“可现在没有了。”\n经理深表同情但却无能为力。\n“现在大家都在丢钱”他说。\n他开始抱怨起这个邪恶的世道来却被一阵敲门声打断了。\n一个姑娘走了进来把一个信封放在了他桌上。\n它里面装着50英镑。\n“这是我在这位先生的房门外捡到的”她说。\n“是啊”我对那位经理说“这世界上还是有诚实可言的”",
"newWords": [],
"textAllWords": [],
"audioSrc": "/public/sound/article/nce2-1/12Goodbye and Good Luck.mp3",
"lrcPosition": []
"audioSrc": "/public/sound/article/nce2-1/24It could be worse.mp3",
"lrcPosition": [[15.33,20.13],[20.13,26.39],[26.39,33.33],[33.33,38.93],[38.93,44.08],[44.08,52.53],[52.53,56.98],[56.98,59.97],[59.97,65.16],[65.16,72.48]]
},
{
"id": "6zEtRS",
"title": "Do the English speak English?",

View File

@@ -1,16 +0,0 @@
[al:新概念英语(二)]
[ar:MP3 同步字幕版(美音)]
[ti:Goodbye and Good Luck]
[by:更多学习内容请到VeryCD.com搜索“露珠”]
[00:10.64]Where is Captain Alison going and how?
[00:16.15]Our neighbour, Captain Charles Alison, will sail from Portsmouth tomorrow.
[00:23.68]We'll meet him at the harbour early in the morning.
[00:27.51]He will be in his small boat, Topsail.
[00:31.64]Topsail is a famous little boat.
[00:34.97]It has sailed across the Atlantic many times.
[00:39.48]Captain Alison will set out at eight o'clock,
[00:43.04]so we'll have plenty of time.
[00:46.00]We'll see his boat and then we'll say goodbye to him.
[00:50.16]He will be away for two months.
[00:53.09]We are very proud of him.
[00:55.91]He will take part in an important race across the Atlantic.

View File

@@ -1,15 +0,0 @@
[al:新概念英语(二)]
[ar:MP3 同步字幕版(美音)]
[ti:The Greenwood Boys]
[by:更多学习内容请到VeryCD.com搜索“露珠”]
[00:09.99]Why will the police have a difficult time?
[00:15.28]The Greenwood Boys are a group of pop singers.
[00:19.38]At present, they are visiting all parts of the country.
[00:24.48]They will be arriving here tomorrow.
[00:27.76]They will be coming by train and most of the young people in the town will be meeting them at the station.
[00:35.81]Tomorrow evening they will be singing at the Workers' Club.
[00:40.82]The Greenwood Boys will be staying for five days.
[00:45.24]During this time, they will give five performances.
[00:50.16]As usual, the police will have a difficult time.
[00:54.70]They will be trying to keep order.
[00:57.56]It is always the same on these occasions.

View File

@@ -1,18 +0,0 @@
[al:新概念英语(二)]
[ar:MP3 同步字幕版(美音)]
[ti:Do You Speak English?]
[by:更多学习内容请到VeryCD.com搜索“露珠”]
[00:10.47]Did the young man speak English?
[00:15.27]I had an amusing experience last year.
[00:19.24]After I had left a small village in the south of France,
[00:23.47]I drove on to the next town.
[00:26.82]On the way, a young man waved to me.
[00:30.58]I stopped and he asked me for a lift.
[00:34.62]As soon as he had got into the car,
[00:37.90]I said good morning to him in French and he replied in the same language.
[00:44.36]Apart from a few words,
[00:46.65]I do not know any French at all.
[00:50.17]Neither of us spoke during the journey.
[00:53.32]I had nearly reached the town, when the young man suddenly said, very slowly,
[01:00.63]'Do you speak English?'
[01:04.63]As I soon learnt, he was English himself!

View File

@@ -1,16 +0,0 @@
[al:新概念英语(二)]
[ar:MP3 同步字幕版(美音)]
[ti:Good News]
[by:更多学习内容请到VeryCD.com搜索“露珠”]
[00:09.78]What was the good news?
[00:13.88]The secretary told me that Mr. Harmsworth would see me.
[00:19.28]I felt very nervous when I went into his office.
[00:24.36]He did not look up from his desk when I entered.
[00:28.84]After I had sat down,
[00:31.23]he said that business was very bad.
[00:35.10]He told me that the firm could not afford to pay such large salaries.
[00:41.52]Twenty people had already left.
[00:45.06]I knew that my turn had come.
[00:48.59]'Mr. Harmsworth,' I said in a weak voice.
[00:53.30]'Don't interrupt,' he said.
[00:56.14]Then he smiled and told me I would receive an extra thousand pounds a year!

View File

@@ -1,15 +0,0 @@
[al:新概念英语(二)]
[ar:MP3 同步字幕版(美音)]
[ti:A Polite Request]
[by:更多学习内容请到VeryCD.com搜索“露珠”]
[00:10.02]What was the polite request?
[00:14.64]If you park your car in the wrong place,
[00:18.11]a traffic policeman will soon find it.
[00:21.68]You will be very lucky if he lets you go without a ticket.
[00:26.86]However, this does not always happen.
[00:31.48]Traffic police are sometimes very polite.
[00:35.98]During a holiday in Sweden,
[00:38.66]I found this note on my car:
[00:42.04]'sir, we welcome you to our city. This is a No Parking area.
[00:49.85]You will enjoy your stay here if you pay attention to our street signs. This note is only a reminder.'
[01:00.31]If you receive a request like this, you cannot fail to obey it!

View File

@@ -1,15 +0,0 @@
[al:新概念英语(二)]
[ar:MP3 同步字幕版(美音)]
[ti:Always Young]
[by:更多学习内容请到VeryCD.com搜索“露珠”]
[00:10.34]Why doesn't Aunt Jennifer tell anyone how old she is?
[00:17.39]My aunt Jennifer is an actress.
[00:20.95]She must be at least thirty-five years old.
[00:25.21]In spite of this, she often appears on the stage as a young girl.
[00:31.68]Jennifer will have to take part in a new play soon.
[00:36.10]This time, she will be a girl of seventeen.
[00:41.18]In the play, she must appear in a bright red dress and long black stockings.
[00:49.17]Last year in another play,
[00:51.70]she had to wear short socks and a bright, orange-coloured dress.
[00:58.45]If anyone ever asks her how old she is,
[01:02.55]she always answers, 'Darling, it must be terrible to be grown up!'

View File

@@ -1,14 +0,0 @@
[al:新概念英语(二)]
[ar:MP3 同步字幕版(美音)]
[ti:He Often does This]
[by:更多学习内容请到VeryCD.com搜索“露珠”]
[00:09.56]What had happened to the writer's bag?
[00:14.28]After I had had lunch at a village pub, I looked for my bag.
[00:20.98]I had left it on a chair beside the door and now it wasn't there!
[00:27.45]As I was looking for it, the landlord came in.
[00:32.45]'Did you have a good meal?' he asked.
[00:35.94]'Yes, thank you,' I answered, 'but I can't pay the bill. I haven't got my bag.'
[00:44.30]The landlord smiled and immediately went out.
[00:48.80]In a few minutes he returned with my bag and gave it back to me.
[00:54.93]'I'm very sorry,' he said.
[00:58.43]'My dog had taken it into the garden. He often does this!'

View File

@@ -1,20 +0,0 @@
[al:新概念英语(二)]
[ar:MP3 同步字幕版(美音)]
[ti:Sold Out]
[by:更多学习内容请到VeryCD.com搜索“露珠”]
[00:10.20]When will the writer see the play?
[00:15.14]'The play may begin at any moment,' I said.
[00:19.47]'It may have begun already,' Susan answered.
[00:24.55]I hurried to the ticket office.
[00:27.78]'May I have two tickets please?' I asked.
[00:32.35]'I'm sorry, we've sold out,' the girl said.
[00:37.10]'What a pity!' Susan exclaimed.
[00:41.51]Just then, a man hurried to the ticket office.
[00:46.59]'Can I return these two tickets?' he asked.
[00:51.15]'Certainly,' the girl said.
[00:55.05]I went back to the ticket office at once.
[00:59.44]'Could I have those two tickets please?' I asked.
[01:05.21]'Certainly,' the girl said,
[01:08.69]'but they're for next Wednesday's performance.
[01:12.40]Do you still want them?'
[01:15.35]'I might as well have them,' I said sadly.

View File

@@ -1,19 +0,0 @@
[al:新概念英语(二)]
[ar:MP3 同步字幕版(美音)]
[ti:One Man in a Boat]
[by:更多学习内容请到VeryCD.com搜索“露珠”]
[00:11.03]Why is fishing the writer's favourite sport?
[00:15.90]Fishing is my favourite sport.
[00:18.88]I often fish for hours without catching anything.
[00:24.11]But this does not worry me.
[00:27.65]Some fishermen are unlucky.
[00:30.69]Instead of catching fish,
[00:33.27]they catch old boots and rubbish.
[00:37.33]I am even less lucky.
[00:40.24]I never catch anything -- not even old boots.
[00:46.48]After having spent whole mornings on the river,
[00:50.52]I always go home with an empty bag.
[00:54.86]'You must give up fishing!' my friends say. 'It's a waste of time.'
[01:02.50]But they don't realize one important thing.
[01:07.05]I'm not really interested in fishing.
[01:10.78]I am only interested in sitting in a boat and doing nothing at all!

View File

@@ -1,14 +0,0 @@
[al:新概念英语(二)]
[ar:MP3 同步字幕版(美音)]
[ti:Mad or Not?]
[by:更多学习内容请到VeryCD.com搜索“露珠”]
[00:10.51]Why do people think the writer is mad?
[00:15.83]Aeroplanes are slowly driving me mad.
[00:20.58]I live near an airport and passing planes can be heard night and day.
[00:27.20]The airport was built years ago, but for some reason it could not be used then.
[00:34.93]Last year, however, it came into use.
[00:39.66]Over a hundred people must have been driven away from their homes by the noise.
[00:46.47]I am one of the few people left.
[00:50.39]Sometimes I think this house will be knocked down by a passing plane.
[00:57.24]I have been offered a large sum of money to go away, but I am determined to stay here.
[01:05.82]Everybody says I must be mad and they are probably right.

View File

@@ -1,12 +0,0 @@
[al:新概念英语(二)]
[ar:MP3 同步字幕版(美音)]
[ti:A Glass Envelope]
[by:更多学习内容请到VeryCD.com搜索“露珠”]
[00:10.79]How did Jane receive a letter from a stranger?
[00:16.79]My daughter, Jane, never dreamed of receiving a letter from a girl of her own age in Holland.
[00:26.87]Last year, we were travelling across the Channel and Jane put a piece of paper with her name and address on it into a bottle.
[00:37.71]She threw the bottle into the sea.
[00:41.19]She never thought of it again, but ten months later, she received a letter from a girl in Holland.
[00:49.93]Both girls write to each other regularly now.
[00:54.19]However, they have decided to use the post office.
[00:59.72]Letters will cost a little more, but they will certainly travel faster.

View File

@@ -1,16 +0,0 @@
[al:新概念英语(二)]
[ar:MP3 同步字幕版(美音)]
[ti:A New House]
[by:更多学习内容请到VeryCD.com搜索“露珠”]
[00:10.53]Why is the new house special?
[00:15.29]I had a letter from my sister yesterday.
[00:19.23]She lives in Nigeria.
[00:22.23]In her letter, she said that she would come to England next year.
[00:28.38]If she comes, she will get a surprise.
[00:32.58]We are now living in a beautiful new house in the country.
[00:37.85]Work on it had begun before my sister left.
[00:42.58]The house was completed five months ago.
[00:46.50]In my letter, I told her that she could stay with us.
[00:51.52]The house has many large rooms and there is a lovely garden.
[00:57.35]It is a very modern house, so it looks strange to some people.
[01:03.69]It must be the only modern house in the district.

View File

@@ -1,15 +0,0 @@
[al:新概念英语(二)]
[ar:MP3 同步字幕版(美音)]
[ti:It Could be Worse]
[by:更多学习内容请到VeryCD.com搜索“露珠”]
[00:10.39]Had the writer's money been stolen?
[00:15.33]I entered the hotel manager's office and sat down.
[00:20.13]I had just lost £50 and I felt very upset.
[00:26.39]'I left the money in my room,' I said, 'and it's not there now. '
[00:33.33]The manager was sympathetic, but he could do nothing.
[00:38.93]'Everyone's losing money these days,' he said.
[00:44.08]He started to complain about this wicked world but was interrupted by a knock at the door.
[00:52.53]A girl came in and put an envelope on his desk.
[00:56.98]It contained £50.
[00:59.97]'I found this outside this gentleman's room,' she said.
[01:05.16]'Well,' I said to the manager,'there is still some honesty in this world!'

View File

@@ -3,19 +3,16 @@ import {onMounted, watch} from "vue";
import {BaseState, useBaseStore} from "@/stores/base.ts";
import {useRuntimeStore} from "@/stores/runtime.ts";
import {useSettingStore} from "@/stores/setting.ts";
import {cloneDeep} from "lodash-es";
import Backgorund from "@/pages/pc/components/Backgorund.vue";
import useTheme from "@/hooks/theme.ts";
import * as localforage from "localforage";
import SettingDialog from "@/pages/pc/components/dialog/SettingDialog.vue";
import ArticleContentDialog from "@/pages/pc/components/dialog/ArticleContentDialog.vue";
import CollectNotice from "@/pages/pc/components/CollectNotice.vue";
import {SAVE_DICT_KEY, SAVE_SETTING_KEY} from "@/utils/const.ts";
import {isMobile, shakeCommonDict} from "@/utils";
import router, {routes} from "@/router.ts";
import {useRoute} from "vue-router";
import {splitEnArticle} from "@/hooks/article.ts";
const store = useBaseStore()
const runtimeStore = useRuntimeStore()
@@ -81,7 +78,6 @@ watch(() => route.path, (to, from) => {
</transition>
</router-view>
<CollectNotice/>
<ArticleContentDialog/>
<SettingDialog/>
</template>

View File

@@ -143,6 +143,12 @@ html.dark {
.anim {
transition: background var(--anim-time), color var(--anim-time), border var(--anim-time);
}
.en-article-family {
font-family: var(--en-article-family);
}
.font-family {
font-family: var(--font-family);
}
html, body {
//font-size: 1px;
@@ -412,25 +418,6 @@ footer {
}
}
&.border {
&.active {
.item-title {
border-bottom: 2px solid gray !important;
}
}
.item-title {
transition: all .3s;
cursor: pointer;
border-bottom: 2px solid transparent;
}
&:hover {
.item-title {
border-bottom: 2px solid gray !important;
}
}
}
.item-title {
display: flex;

View File

@@ -0,0 +1,99 @@
<template>
<div class="question-form en-article-family">
<div class="flex items-center justify-between">
<div class="font-bold">Multiple choice questions 选择题</div>
<div v-if="false">
<button
v-if="!started"
class="bg-blue-600 text-white px-4 py-1 rounded"
@click="startExam"
>开始
</button>
<span v-if="started" class="text-red-600 font-semibold font-family">
倒计时{{ timeLeft }}
</span>
</div>
</div>
<form @submit.prevent>
<QuestionItem
v-for="(q, i) in questions"
:key="i"
ref="questionRefs1"
:question-index="i + 1"
:stem="q.stem"
:options="q.options"
:correct-answer="q.correctAnswer"
:explanation="q.explanation"
:immediate-feedback="props.immediateFeedback"
:randomize="props.randomize"
@answered="onAnswered"
/>
</form>
<div class="flex-center items-center gap-2 mt-10">
<button
class="bg-green-600 text-white px-6 py-2 rounded"
@click="submitAll"
>提交试卷
</button>
<span class="text-xl">浅红错误 深红未选 绿正确</span>
</div>
</div>
</template>
<script setup lang="ts">
import {ref, useTemplateRef} from 'vue'
import QuestionItem from './QuestionItem.vue'
interface IProps {
questions: Array,
duration: Number,
immediateFeedback: Boolean,
randomize: Boolean
}
const props = withDefaults(defineProps<IProps>(), {
questions: [],
duration: 300,
immediateFeedback: false,
randomize: false
})
const questionRefs = useTemplateRef('questionRefs1')
const started = ref(false)
const timeLeft = ref(props.duration || 300)
let timer = null
const startExam = () => {
started.value = true
timeLeft.value = props.duration || 300
timer = setInterval(() => {
timeLeft.value--
if (timeLeft.value <= 0) {
clearInterval(timer)
submitAll()
}
}, 1000)
}
const onAnswered = (res) => {
console.log('Answered:', res)
// 可收集中间过程(非必须)
}
const submitAll = () => {
console.log(questionRefs)
questionRefs.value.forEach((q) => q.submit())
const results = questionRefs.value.map((q) => q.getResult())
const correctCount = results.filter(r => r.isCorrect).length
const wrongCount = results.length - correctCount
console.log('最终结果:', results)
ElMessage({message: `${results.length} 题,答对 ${correctCount},答错 ${wrongCount}`})
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,194 @@
<template>
<div ref="container" class="question-item mb-4">
<div class="mb-1 "
:class="noChoseClass"
><span class="font-family">{{ questionIndex }}</span>. {{ stem }}
</div>
<div
class="grid gap-1"
:class="layoutClass"
>
<label
v-for="(opt, i) in shuffledOptions"
:key="i"
class="option border rounded cursor-pointer hover:bg-gray-300"
:class="feedbackClass(i)"
>
<input
:type="isMultiple ? 'checkbox' : 'radio'"
:name="`question-${questionIndex}`"
class="mr-2"
:value="opt"
v-model="userSelection"
@change="onSelect"
/>
<span ref="optionRefs">(<span class="italic">{{ ['a', 'b', 'c', 'd'][i] }}</span>) {{ opt }}</span>
</label>
</div>
<div v-if="explanation && isSubmitted" class="mt-2 text-xl text-gray-600">
解析{{ explanation }}
</div>
</div>
</template>
<script setup>
import {ref, computed, watch, onMounted, nextTick} from 'vue'
import {shuffle} from "lodash-es";
const props = defineProps({
stem: String,
options: Array,
correctAnswer: Array, // ['a', 'b']
explanation: String,
immediateFeedback: Boolean,
questionIndex: Number,
randomize: Boolean
})
const emit = defineEmits(['answered'])
// 将选项打乱并映射回原始下标
const originalOptions = props.options
const shuffledOptions = ref([])
const answerMap = ref([]) // 映射 shuffled[i] 对应原始 index用于判分
const isMultiple = computed(() => props.correctAnswer.length > 1)
const userSelection = ref(isMultiple.value ? [] : '')
const isSubmitted = ref(false)
const isCorrect = ref(null)
// 初始化打乱选项
const initOptions = () => {
const indices = originalOptions.map((_, i) => i)
const shuffledIndices = props.randomize ? shuffle(indices) : indices
shuffledOptions.value = shuffledIndices.map(i => originalOptions[i])
answerMap.value = shuffledIndices
}
initOptions()
const getLetter = (index) => ['a', 'b', 'c', 'd'][index]
const getOriginalLetter = (shuffledIndex) => getLetter(answerMap.value[shuffledIndex])
const onSelect = () => {
if (props.immediateFeedback) submit()
emitAnswer()
}
const emitAnswer = () => {
const selectedLetters = isMultiple.value
? userSelection.value.map(val => getOriginalLetter(shuffledOptions.value.indexOf(val)))
: [getOriginalLetter(shuffledOptions.value.indexOf(userSelection.value))]
const isAnswerCorrect =
selectedLetters.sort().join() === props.correctAnswer.sort().join()
emit('answered', {
index: props.questionIndex,
selected: selectedLetters,
isCorrect: isAnswerCorrect
})
}
const submit = () => {
isSubmitted.value = true
const selectedLetters = isMultiple.value
? userSelection.value.map(val => getOriginalLetter(shuffledOptions.value.indexOf(val)))
: [getOriginalLetter(shuffledOptions.value.indexOf(userSelection.value))]
isCorrect.value =
selectedLetters.sort().join() === props.correctAnswer.sort().join()
}
const feedbackClass = (i) => {
if (!isSubmitted.value) return ''
const selected = isMultiple.value
? userSelection.value.includes(shuffledOptions.value[i])
: userSelection.value === shuffledOptions.value[i]
const correct = props.correctAnswer.includes(getOriginalLetter(i))
if (correct) return 'bg-green-200'
if (selected && !correct) return 'bg-red-200'
return ''
}
const noChoseClass = computed(() => {
if (!isSubmitted.value) return ''
const selected = isMultiple.value
? userSelection.value.length
: userSelection.value
return !selected && 'bg-red-400'
})
// 父组件调用此方法统一评分
defineExpose({
submit,
getResult: () => {
const selectedLetters = isMultiple.value
? userSelection.value.map(val => getOriginalLetter(shuffledOptions.value.indexOf(val)))
: [getOriginalLetter(shuffledOptions.value.indexOf(userSelection.value))]
return {
index: props.questionIndex,
selected: selectedLetters,
isCorrect: selectedLetters.sort().join() === props.correctAnswer.sort().join()
}
}
})
const optionRefs = ref([])
const container = ref(null)
const layoutClass = ref('')
const calculateLayout = () => {
if (!container.value || optionRefs.value.length === 0) return
const containerWidth = container.value.clientWidth
const widths = optionRefs.value.map(el => el.getBoundingClientRect().width)
const totalWidth = widths.reduce((sum, w) => sum + w, 0)
// console.log(widths,totalWidth)
// 如果任意选项宽度超过容器一半
if (widths.some(w => w > containerWidth / 2)) {
layoutClass.value = 'grid-cols-1'
return
}
// 如果所有选项都可以在一行内放下
if (totalWidth + 80 * (widths.length - 1) <= containerWidth) {
layoutClass.value = 'grid-cols-4'
return
}
// 否则 2 列
layoutClass.value = 'grid-cols-2'
}
onMounted(async () => {
await nextTick()
calculateLayout()
const resizeObserver = new ResizeObserver(() => {
calculateLayout()
})
resizeObserver.observe(container.value)
})
watch(() => props.options, async () => {
await nextTick()
calculateLayout()
})
</script>
<style scoped>
.option {
white-space: normal;
text-overflow: unset;
overflow: visible;
word-break: keep-all;
padding: 5px;
border-radius: 6px;
transition: all 0.2s ease;
}
</style>

View File

@@ -1,97 +0,0 @@
<script setup lang="ts">
import Dialog from "@/pages/pc/components/dialog/Dialog.vue";
import {onMounted, onUnmounted, watch} from "vue";
import {emitter, EventKey} from "@/utils/eventBus.ts";
import {useRuntimeStore} from "@/stores/runtime.ts";
import WordList from "@/pages/pc/components/list/WordList.vue";
import {Article, DefaultArticle} from "@/types.ts";
import {cloneDeep} from "lodash-es";
import Empty from "@/components/Empty.vue";
import {getTranslateText} from "@/hooks/article.ts";
let show = $ref(false)
let loading = $ref(false)
const runtimeStore = useRuntimeStore()
let article: Article = $ref(cloneDeep(DefaultArticle))
onMounted(() => {
emitter.on(EventKey.openArticleContentModal, (val: any) => {
show = true
article = cloneDeep(val)
})
})
onUnmounted(() => {
emitter.off(EventKey.openArticleContentModal)
})
</script>
<template>
<Dialog
:header="false"
v-model="show">
<div class="content">
<div class="article-content">
<div class="title">
<div>{{ article.title }}</div>
</div>
<div class="text" v-if="article.text">
<div class="sentence" v-for="t in article.text.split('\n\n')">{{ t }}</div>
</div>
<Empty v-else/>
</div>
<div class="article-content">
<div class="title">
<div>{{ article.titleTranslate }}</div>
</div>
<div class="text" v-if="getTranslateText(article).length">
<div class="sentence" v-for="t in getTranslateText(article)">{{ t }}</div>
</div>
<Empty v-else/>
</div>
</div>
</Dialog>
</template>
<style lang="scss" scoped>
@import "@/assets/css/style";
.content {
width: 70vw;
height: 75vh;
display: flex;
gap: var(--space);
padding: var(--space);
color: var(--color-font-1);
.article-content {
flex: 1;
overflow: hidden;
font-size: 1.2rem;
display: flex;
flex-direction: column;
.title {
text-align: center;
margin-bottom: var(--space);
font-size: 1.4rem;
}
.text {
text-indent: 1.5em;
line-height: 2rem;
overflow: auto;
padding-right: .6rem;
padding-bottom: 3rem;
.sentence {
margin-bottom: 1rem;
}
}
}
}
</style>

View File

@@ -59,7 +59,7 @@ defineExpose({scrollToBottom, scrollToItem})
<slot name="prefix" :item="item" :index="index"></slot>
</template>
<template v-slot="{ item, index }">
<div class="item-title" @click.stop="emit('title',{item,index})">
<div class="item-title" >
<div class="name"> {{ `${searchKey ? '' : (index + 1) + '. '}${item.title}` }}</div>
</div>
<div class="item-sub-title" v-if="item.titleTranslate && showTranslate">

View File

@@ -7,14 +7,12 @@ const props = withDefaults(defineProps<{
activeIndex?: number,
activeId?: string,
isActive?: boolean
showBorder?: boolean
static?: boolean
}>(), {
list: [],
activeIndex: -1,
activeId: '',
isActive: false,
showBorder: false,
static: true
})
@@ -124,7 +122,6 @@ defineExpose({scrollToBottom, scrollToItem})
<div class="common-list-item"
:class="{
active:itemIsActive(item,index),
border:showBorder
}"
@click="emit('click',{item,index})"
>
@@ -154,7 +151,6 @@ defineExpose({scrollToBottom, scrollToItem})
<div class="common-list-item"
:class="{
active:itemIsActive(item,index),
border:showBorder
}"
@click="emit('click',{item,index})"
>

View File

@@ -362,7 +362,6 @@ defineExpose({getDictDetail, add, editDict})
<BaseIcon
style="position:absolute;right: 0;"
title="大屏显示"
@click="emitter.emit(EventKey.openArticleContentModal,article)"
icon="iconoir:expand"/>
</div>
<div class="text" v-if="article.text">
@@ -376,7 +375,6 @@ defineExpose({getDictDetail, add, editDict})
<BaseIcon
style="position:absolute;right: 0;"
title="大屏显示"
@click="emitter.emit(EventKey.openArticleContentModal,article)"
icon="iconoir:expand"/>
</div>
<div class="text" v-if="getTranslateText(article).length">

View File

@@ -15,6 +15,7 @@ import {useToast} from 'vue-toast-notification';
import 'vue-toast-notification/dist/theme-sugar.css';
import {getTranslateText} from "@/hooks/article.ts";
import BaseButton from "@/components/BaseButton.vue";
import QuestionForm from "@/pages/pc/components/QuestionForm.vue";
interface IProps {
article: Article,
@@ -348,7 +349,6 @@ onMounted(() => {
wrong = input = ''
})
emitter.on(EventKey.onTyping, onTyping)
})
onUnmounted(() => {
@@ -358,15 +358,106 @@ onUnmounted(() => {
defineExpose({showSentence, play, del, hideSentence, nextSentence})
let list = $ref([
{
stem: "The writer thought_____?",
options: [
"he had lost his money",
"someone had stolen his money",
"the manager had the money",
"the girl had stolen the money"
],
correctAnswer: ["b"],
explanation: "根据课文第23行'I left the money in my room,'I said, and it's not there now',只有(b)someone had stolen his money 符合作者的推测。其他3个选择都不正确。"
},
{
stem: "What had really happened?",
options: [
"The writer had lost the money.",
"The girl had stolen the money.",
"The manager had taken the money.",
"Someone had stolen the money."
],
correctAnswer: ["a"],
explanation: "根据课文的情节,只有(a)The writer had lost the money是正确的符合课文的原义。(b)The girl had stolen themoney不符合课文的情况因为是这个女孩捡到了钱而不是她偷了钱(c)The manager had taken the money 更与事实不符;(d)Someone had stolen the money与实际情况不符。"
},
{
stem: "The money____ in his room.",
options: ["was", "were", "are", "has"],
correctAnswer: ["a"],
explanation: "(b)were不符合语法因为The money是单数不可数名词故不能用were作谓语动词(c)are 也不合乎语法因为它也不能作money的谓语动词(d)has不符合题义若选(d)此句意思讲不通;只有(a)was合乎语法。"
},
{
stem: "He could do nothing. He couldn't do____.",
options: ["something", "nothing", "anything", "everything"],
correctAnswer: ["c"],
explanation: "只有(c)anything可以用在否定句中。(a)something不能用于否定句(b)nothing若用在否定句中双重否定会变成肯定意义的句子不合题义(d)everything 一般不用于这种否定句中。"
},
{
stem: "A knock at the door____ him.",
options: ["interrupted", "was interrupted", "interrupting", "was interrupting"],
correctAnswer: ["a"],
explanation: "只有(a)interrupted最合乎语法。(b)was interrupted是被动语态这个句子不应该是被动语态。(c)interrupting是现在分词不能作谓语。(d)was interrupting是过去进行时interrupt(打断)是表示一个瞬间动作,即敲门声是一下子打断了他的话,而不是正在打断。故应该用一般过去时,不应该用过去进行时。"
},
{
stem: "Where did she find the money? ____ the room.",
options: ["Outside", "Out of", "Out", "Without"],
correctAnswer: ["a"],
explanation: "(a)Outside(prep.在……外)最符合逻辑,因为只有(a)能回答地点where。(b)Out of(prep.从……里面……)强调从里面向外,不合乎题义;(c)out不是介词因此不能同 the room 构成表示地点的短语;(d)without(prep.没有)不表示地点,更不符合题义。"
},
{
stem: "____ room was it? — This gentleman's.",
options: ["To whom", "Who", "Whose", "Of whom"],
correctAnswer: ["c"],
explanation: "这是一个对定语(所有格)提问的疑问句。(a)To whom是对宾语提问(b)Who是对主语提问(d)Of whom 也是对宾语提问;只有(c)Whose(谁的)是对定语提问,所以应该选(c)。"
},
{
stem: "The writer had lost his money. He felt upset. He must have been____.",
options: ["sick", "ill", "worried", "tired"],
correctAnswer: ["c"],
explanation: "只有(c)worried(着急,忧虑)同前一句中的upset(不安)意思相近。(a)sick(有病的,恶心的)、(b)ill(有病的)与(d)tired(疲劳的,厌倦的)这3个选择都不合乎题义。"
},
{
stem: "The manager was sympathetic. ____.",
options: [
"Everyone liked him",
"He liked everyone",
"He was sorry for the writer",
"He liked the writer"
],
correctAnswer: ["c"],
explanation: "只有(c)He was sorry for the writer(他为作者感到难过或惋惜)才能解释前面的句子The manager was sympathetic(表示同情的)。而其他3个选择(a)Everyone liked him(每个人都喜欢他)、(b)He liked everyone(他喜欢每个人)与(d)He liked the writer(他喜欢作者)都与前句意思不符。"
},
{
stem: "He lost his money. His money was____.",
options: ["losing", "missing", "going away", "disappearing"],
correctAnswer: ["b"],
explanation: "(a)losing(丢失)不正确。若选(a)主语应该是人而不应该是money;(c)going away(走开,离开)词义不对;(d)disappearing(消失,失踪)词义不够恰当;只有(b)missing(丢掉的,失去的)词义最准确,而且可以作表语。"
},
{
stem: "You can't post this letter without____.",
options: ["an envelope", "a packet", "some string", "a pen"],
correctAnswer: ["a"],
explanation: "只有选(a)an envelope(信封)最合乎逻辑和事实。(b)apacket(一包)、(c)some string(一些细绳)和(d)a pen(一枝钢笔)这3个选择都不符合实际情况。"
},
{
stem: "The girl returned the money. She was very____.",
options: ["honourable", "honest", "honoured", "trusting"],
correctAnswer: ["b"],
explanation: "只有选(b)honest(诚实的)最合乎逻辑。(a)honourable(光荣的,体面的)、(c)honoured(感到荣幸的,受到尊敬的)与(d)trusting(信任的)这3个词都不如honest合乎逻辑。"
}
])
let show = $ref(false)
</script>
<template>
<div class="typing-article" ref="typeArticleRef">
<header class="mb-4">
<div class="title word">{{ props.article.title }}</div>
<div class="titleTranslate" v-if="settingStore.translate">{{ props.article.titleTranslate }}</div>
</header>
<div class="article-content" ref="articleWrapperRef">
<article :class="[
settingStore.translate && 'tall',
@@ -449,12 +540,15 @@ defineExpose({showSentence, play, del, hideSentence, nextSentence})
</div>
<div class="cursor" v-if="!isEnd" :style="{top:cursor.top+'px',left:cursor.left+'px'}"></div>
</div>
<div class="options flex justify-center" v-if="isEnd">
<BaseButton
v-if="store.currentArticleDict.lastLearnIndex < store.currentArticleDict.articles.length - 1"
@click="emitter.emit(EventKey.next)">下一章</BaseButton>
@click="emitter.emit(EventKey.next)">下一章
</BaseButton>
</div>
<div class="translate-bottom" v-if="settingStore.translate">
<div class="translate-bottom mb-10" v-if="settingStore.translate">
<header class="mb-4">
<div class="text-2xl center">{{ props.article.titleTranslate }}</div>
</header>
@@ -462,6 +556,18 @@ defineExpose({showSentence, play, del, hideSentence, nextSentence})
<div class="text-xl mb-4 indent-8" v-for="t in getTranslateText(article)">{{ t }}</div>
</template>
</div>
<div class="flex-center">
<BaseButton @click="show =! show">显示题目</BaseButton>
</div>
<div class="toggle" v-if="show">
<QuestionForm :questions="list"
:duration="300"
:immediateFeedback="false"
:randomize="true"
/>
</div>
</div>
</template>
@@ -478,6 +584,7 @@ defineExpose({showSentence, play, del, hideSentence, nextSentence})
width: 100%;
overflow: auto;
color: var(--color-article);
font-size: 1.6rem;
header {
word-wrap: break-word;
@@ -504,7 +611,6 @@ defineExpose({showSentence, play, del, hideSentence, nextSentence})
}
article {
font-size: 1.6rem;
line-height: 1.3;
word-break: keep-all;
word-wrap: break-word;

View File

@@ -115,6 +115,7 @@ function getCurrentPractice() {
function saveArticle(val: Article) {
console.log('saveArticle', val, JSON.stringify(val.lrcPosition))
console.log('saveArticle', val.textTranslate)
showEditArticle = false
let rIndex = store.currentArticleDict.articles.findIndex(v => v.id === val.id)
if (rIndex > -1) {
@@ -347,9 +348,7 @@ const {playSentenceAudio} = usePlaySentenceAudio()
<ArticleList
:isActive="active"
:static="false"
:show-border="true"
:show-translate="settingStore.translate"
@title="e => emitter.emit(EventKey.openArticleContentModal,e.item)"
@click="handleChangeChapterIndex"
:active-id="articleData.article.id"
:list="articleData.articles ">

View File

@@ -132,7 +132,7 @@ export const DefaultBaseState = (): BaseState => ({
type: DictType.article,
resourceId: 'article_nce2',
length: 96,
lastLearnIndex:10
lastLearnIndex:23
},
],
wordDictList: [

View File

@@ -7,7 +7,6 @@ export const EventKey = {
changeDict: 'changeDict',
openStatModal: 'openStatModal',
openWordListModal: 'openWordListModal',
openArticleContentModal: 'openArticleContentModal',
openDictModal: 'openDictModal',
openArticleListModal: 'openArticleListModal',
closeOther: 'closeOther',