├── dist
├── favicon.ico
├── index.html
└── assets
│ └── index-edcbd76c.css
├── public
└── favicon.ico
├── .vscode
└── extensions.json
├── src
├── main.js
├── assets
│ ├── logo.svg
│ ├── main.css
│ └── base.css
├── components
│ ├── icons
│ │ ├── IconSupport.vue
│ │ ├── IconTooling.vue
│ │ ├── IconCommunity.vue
│ │ ├── IconDocumentation.vue
│ │ └── IconEcosystem.vue
│ ├── HelloWorld.vue
│ ├── WelcomeItem.vue
│ └── TheWelcome.vue
├── libs
│ ├── xlsx.js
│ └── generator-timu.js
└── App.vue
├── vite.config.js
├── index.html
├── .gitignore
├── package.json
└── README.md
/dist/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/excel2word/develop/dist/favicon.ico
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yjj5855/excel2word/develop/public/favicon.ico
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"]
3 | }
4 |
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import { createApp } from 'vue'
2 | import App from './App.vue'
3 |
4 | import './assets/main.css'
5 |
6 | createApp(App).mount('#app')
7 |
--------------------------------------------------------------------------------
/src/assets/logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/components/icons/IconSupport.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
--------------------------------------------------------------------------------
/vite.config.js:
--------------------------------------------------------------------------------
1 | import { fileURLToPath, URL } from 'node:url'
2 |
3 | import { defineConfig } from 'vite'
4 | import vue from '@vitejs/plugin-vue'
5 |
6 | // https://vitejs.dev/config/
7 | export default defineConfig({
8 | plugins: [vue()],
9 | resolve: {
10 | alias: {
11 | '@': fileURLToPath(new URL('./src', import.meta.url))
12 | }
13 | }
14 | })
15 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite App
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | .DS_Store
12 | #dist
13 | dist-ssr
14 | coverage
15 | *.local
16 |
17 | /cypress/videos/
18 | /cypress/screenshots/
19 |
20 | # Editor directories and files
21 | .vscode/*
22 | !.vscode/extensions.json
23 | .idea
24 | *.suo
25 | *.ntvs*
26 | *.njsproj
27 | *.sln
28 | *.sw?
29 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "excel2word",
3 | "version": "0.0.0",
4 | "private": true,
5 | "scripts": {
6 | "dev": "vite",
7 | "build": "vite build",
8 | "preview": "vite preview"
9 | },
10 | "dependencies": {
11 | "docx": "^7.8.2",
12 | "file-saver": "^2.0.5",
13 | "vue": "^3.2.45",
14 | "xlsx": "^0.18.5"
15 | },
16 | "devDependencies": {
17 | "@vitejs/plugin-vue": "^4.0.0",
18 | "vite": "^4.0.0"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/dist/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite App
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/assets/main.css:
--------------------------------------------------------------------------------
1 | @import './base.css';
2 |
3 | #app {
4 | max-width: 1280px;
5 | margin: 0 auto;
6 | padding: 2rem;
7 |
8 | font-weight: normal;
9 | }
10 |
11 | a,
12 | .green {
13 | text-decoration: none;
14 | color: hsla(160, 100%, 37%, 1);
15 | transition: 0.4s;
16 | }
17 |
18 | @media (hover: hover) {
19 | a:hover {
20 | background-color: hsla(160, 100%, 37%, 0.2);
21 | }
22 | }
23 |
24 | @media (min-width: 1024px) {
25 | body {
26 | display: flex;
27 | place-items: center;
28 | }
29 |
30 | #app {
31 | display: grid;
32 | grid-template-columns: 1fr 1fr;
33 | padding: 0 2rem;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # excel2word
2 |
3 | This template should help get you started developing with Vue 3 in Vite.
4 |
5 | ## Recommended IDE Setup
6 |
7 | [VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).
8 |
9 | ## Customize configuration
10 |
11 | See [Vite Configuration Reference](https://vitejs.dev/config/).
12 |
13 | ## Project Setup
14 |
15 | ```sh
16 | npm install
17 | ```
18 |
19 | ### Compile and Hot-Reload for Development
20 |
21 | ```sh
22 | npm run dev
23 | ```
24 |
25 | ### Compile and Minify for Production
26 |
27 | ```sh
28 | npm run build
29 | ```
30 |
--------------------------------------------------------------------------------
/src/components/HelloWorld.vue:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
{{ msg }}
13 |
14 | You’ve successfully created a project with
15 | Vite +
16 | Vue 3.
17 |
18 |
19 |
20 |
21 |
44 |
--------------------------------------------------------------------------------
/src/components/icons/IconTooling.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
19 |
20 |
--------------------------------------------------------------------------------
/src/components/icons/IconCommunity.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
--------------------------------------------------------------------------------
/src/components/icons/IconDocumentation.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
--------------------------------------------------------------------------------
/src/components/WelcomeItem.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
87 |
--------------------------------------------------------------------------------
/src/components/icons/IconEcosystem.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
--------------------------------------------------------------------------------
/dist/assets/index-edcbd76c.css:
--------------------------------------------------------------------------------
1 | header[data-v-5a177b26]{line-height:1.5}.logo[data-v-5a177b26]{display:block;margin:0 auto 2rem}@media (min-width: 1024px){header[data-v-5a177b26]{display:flex;place-items:center;padding-right:calc(var(--section-gap) / 2)}.logo[data-v-5a177b26]{margin:0 2rem 0 0}header .wrapper[data-v-5a177b26]{display:flex;place-items:flex-start;flex-wrap:wrap}}:root{--vt-c-white: #ffffff;--vt-c-white-soft: #f8f8f8;--vt-c-white-mute: #f2f2f2;--vt-c-black: #181818;--vt-c-black-soft: #222222;--vt-c-black-mute: #282828;--vt-c-indigo: #2c3e50;--vt-c-divider-light-1: rgba(60, 60, 60, .29);--vt-c-divider-light-2: rgba(60, 60, 60, .12);--vt-c-divider-dark-1: rgba(84, 84, 84, .65);--vt-c-divider-dark-2: rgba(84, 84, 84, .48);--vt-c-text-light-1: var(--vt-c-indigo);--vt-c-text-light-2: rgba(60, 60, 60, .66);--vt-c-text-dark-1: var(--vt-c-white);--vt-c-text-dark-2: rgba(235, 235, 235, .64)}:root{--color-background: var(--vt-c-white);--color-background-soft: var(--vt-c-white-soft);--color-background-mute: var(--vt-c-white-mute);--color-border: var(--vt-c-divider-light-2);--color-border-hover: var(--vt-c-divider-light-1);--color-heading: var(--vt-c-text-light-1);--color-text: var(--vt-c-text-light-1);--section-gap: 160px}@media (prefers-color-scheme: dark){:root{--color-background: var(--vt-c-black);--color-background-soft: var(--vt-c-black-soft);--color-background-mute: var(--vt-c-black-mute);--color-border: var(--vt-c-divider-dark-2);--color-border-hover: var(--vt-c-divider-dark-1);--color-heading: var(--vt-c-text-dark-1);--color-text: var(--vt-c-text-dark-2)}}*,*:before,*:after{box-sizing:border-box;margin:0;position:relative;font-weight:400}body{min-height:100vh;color:var(--color-text);background:var(--color-background);transition:color .5s,background-color .5s;line-height:1.6;font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;font-size:15px;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}#app{max-width:1280px;margin:0 auto;padding:2rem;font-weight:400}a,.green{text-decoration:none;color:#00bd7e;transition:.4s}@media (hover: hover){a:hover{background-color:#00bd7e33}}@media (min-width: 1024px){body{display:flex;place-items:center}#app{display:grid;grid-template-columns:1fr 1fr;padding:0 2rem}}
2 |
--------------------------------------------------------------------------------
/src/assets/base.css:
--------------------------------------------------------------------------------
1 | /* color palette from */
2 | :root {
3 | --vt-c-white: #ffffff;
4 | --vt-c-white-soft: #f8f8f8;
5 | --vt-c-white-mute: #f2f2f2;
6 |
7 | --vt-c-black: #181818;
8 | --vt-c-black-soft: #222222;
9 | --vt-c-black-mute: #282828;
10 |
11 | --vt-c-indigo: #2c3e50;
12 |
13 | --vt-c-divider-light-1: rgba(60, 60, 60, 0.29);
14 | --vt-c-divider-light-2: rgba(60, 60, 60, 0.12);
15 | --vt-c-divider-dark-1: rgba(84, 84, 84, 0.65);
16 | --vt-c-divider-dark-2: rgba(84, 84, 84, 0.48);
17 |
18 | --vt-c-text-light-1: var(--vt-c-indigo);
19 | --vt-c-text-light-2: rgba(60, 60, 60, 0.66);
20 | --vt-c-text-dark-1: var(--vt-c-white);
21 | --vt-c-text-dark-2: rgba(235, 235, 235, 0.64);
22 | }
23 |
24 | /* semantic color variables for this project */
25 | :root {
26 | --color-background: var(--vt-c-white);
27 | --color-background-soft: var(--vt-c-white-soft);
28 | --color-background-mute: var(--vt-c-white-mute);
29 |
30 | --color-border: var(--vt-c-divider-light-2);
31 | --color-border-hover: var(--vt-c-divider-light-1);
32 |
33 | --color-heading: var(--vt-c-text-light-1);
34 | --color-text: var(--vt-c-text-light-1);
35 |
36 | --section-gap: 160px;
37 | }
38 |
39 | @media (prefers-color-scheme: dark) {
40 | :root {
41 | --color-background: var(--vt-c-black);
42 | --color-background-soft: var(--vt-c-black-soft);
43 | --color-background-mute: var(--vt-c-black-mute);
44 |
45 | --color-border: var(--vt-c-divider-dark-2);
46 | --color-border-hover: var(--vt-c-divider-dark-1);
47 |
48 | --color-heading: var(--vt-c-text-dark-1);
49 | --color-text: var(--vt-c-text-dark-2);
50 | }
51 | }
52 |
53 | *,
54 | *::before,
55 | *::after {
56 | box-sizing: border-box;
57 | margin: 0;
58 | position: relative;
59 | font-weight: normal;
60 | }
61 |
62 | body {
63 | min-height: 100vh;
64 | color: var(--color-text);
65 | background: var(--color-background);
66 | transition: color 0.5s, background-color 0.5s;
67 | line-height: 1.6;
68 | font-family: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu,
69 | Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
70 | font-size: 15px;
71 | text-rendering: optimizeLegibility;
72 | -webkit-font-smoothing: antialiased;
73 | -moz-osx-font-smoothing: grayscale;
74 | }
75 |
--------------------------------------------------------------------------------
/src/libs/xlsx.js:
--------------------------------------------------------------------------------
1 | import * as XLSX from 'xlsx'
2 |
3 | export default {
4 | workbook2blob,
5 | openDownloadDialog,
6 | readWorkbookFromLocalFile,
7 | getHeaderKeyList
8 | }
9 | // 将workbook装化成blob对象
10 | function workbook2blob(workbook) {
11 | // 生成excel的配置项
12 | var wopts = {
13 | // 要生成的文件类型
14 | bookType: 'xlsx',
15 | // 是否生成Shared String Table,官方解释是,如果开启生成速度会下降,但在低版本IOS设备上有更好的兼容性
16 | bookSST: false,
17 | // 二进制类型
18 | type: 'binary'
19 | }
20 | var wbout = XLSX.write(workbook, wopts)
21 | var blob = new Blob([s2ab(wbout)], {
22 | type: 'application/octet-stream'
23 | })
24 | return blob
25 | }
26 |
27 | // 将字符串转ArrayBuffer
28 | function s2ab(s) {
29 | var buf = new ArrayBuffer(s.length)
30 | var view = new Uint8Array(buf)
31 | for (var i = 0; i != s.length; ++i) {
32 | view[i] = s.charCodeAt(i) & 0xff
33 | }
34 | return buf
35 | }
36 |
37 | // 将blob对象创建bloburl,然后用a标签实现弹出下载框
38 | function openDownloadDialog(blob, fileName) {
39 | if (typeof blob == 'object' && blob instanceof Blob) {
40 | blob = URL.createObjectURL(blob) // 创建blob地址
41 | }
42 | var aLink = document.createElement('a')
43 | aLink.href = blob
44 | // HTML5新增的属性,指定保存文件名,可以不要后缀,注意,有时候 file:///模式下不会生效
45 | aLink.download = fileName || ''
46 | var event
47 | if (window.MouseEvent) event = new MouseEvent('click')
48 | // 移动端
49 | else {
50 | event = document.createEvent('MouseEvents')
51 | event.initMouseEvent(
52 | 'click',
53 | true,
54 | false,
55 | window,
56 | 0,
57 | 0,
58 | 0,
59 | 0,
60 | 0,
61 | false,
62 | false,
63 | false,
64 | false,
65 | 0,
66 | null
67 | )
68 | }
69 | aLink.dispatchEvent(event)
70 | URL.revokeObjectURL(blob)
71 | }
72 |
73 | // 读取本地excel文件
74 | function readWorkbookFromLocalFile(file, callback) {
75 | var reader = new FileReader();
76 | reader.onload = function(e) {
77 | var data = e.target.result;
78 | // 读取二进制的excel
79 | var workbook = XLSX.read(data, {type: 'binary'});
80 | if(callback) callback(workbook);
81 | };
82 | reader.readAsBinaryString(file);
83 | }
84 |
85 | // 获取excel第一行的内容
86 | function getHeaderKeyList (sheet) {
87 | var wbData = sheet; // 读取的excel单元格内容
88 | var re = /^[A-Z]*1$/; // /^[A-Z]*1$/ 匹配excel第一行的内容
89 | var arr1 = [];
90 | for (var key in wbData) { // excel第一行内容赋值给数组
91 | if (wbData.hasOwnProperty(key)) {
92 | if (re.test(key)) {
93 | arr1.push(wbData[key].h);
94 | }
95 | }
96 | }
97 | return arr1;
98 | }
99 |
--------------------------------------------------------------------------------
/src/components/TheWelcome.vue:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | Documentation
16 |
17 | Vue’s
18 | official documentation
19 | provides you with all information you need to get started.
20 |
21 |
22 |
23 |
24 |
25 |
26 | Tooling
27 |
28 | This project is served and bundled with
29 | Vite. The
30 | recommended IDE setup is
31 | VSCode +
32 | Volar. If
33 | you need to test your components and web pages, check out
34 | Cypress and
35 | Cypress Component Testing.
36 |
37 |
38 |
39 | More instructions are available in README.md.
40 |
41 |
42 |
43 |
44 |
45 |
46 | Ecosystem
47 |
48 | Get official tools and libraries for your project:
49 | Pinia,
50 | Vue Router,
51 | Vue Test Utils, and
52 | Vue Dev Tools. If
53 | you need more resources, we suggest paying
54 | Awesome Vue
55 | a visit.
56 |
57 |
58 |
59 |
60 |
61 |
62 | Community
63 |
64 | Got stuck? Ask your question on
65 | Vue Land, our official
66 | Discord server, or
67 | StackOverflow. You should also subscribe to
70 | our mailing list and follow
71 | the official
72 | @vuejs
73 | twitter account for latest news in the Vue world.
74 |
75 |
76 |
77 |
78 |
79 |
80 | Support Vue
81 |
82 | As an independent project, Vue relies on community backing for its sustainability. You can help
83 | us by
84 | becoming a sponsor.
85 |
86 |
87 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
10 |
11 |
12 |
104 |
105 |
133 |
--------------------------------------------------------------------------------
/src/libs/generator-timu.js:
--------------------------------------------------------------------------------
1 | import {
2 | AlignmentType,
3 | Document,
4 | HeadingLevel,
5 | Packer,
6 | Paragraph,
7 | TabStopPosition,
8 | TabStopType,
9 | TextRun,
10 | NumberValueElement,
11 | Numbering,
12 | TableBorders,
13 | WidthType,
14 | Table,
15 | TableCell,
16 | TableRow, BorderStyle, Columns, Column
17 | } from "docx";
18 |
19 | export class DocumentCreator {
20 | create(sheet) {
21 | let timuList = sheet.timuList.sort((a, b) => a['总序'] < b['总序'])
22 |
23 | let danxuanList = timuList.filter(item => item['题型'] === '单选')
24 | let duoxuanList = timuList.filter(item => item['题型'] === '多选')
25 |
26 | const document = new Document({
27 | styles: {
28 | paragraphStyles: [ // 段落样式
29 | {
30 | id: "subtitle",
31 | name: "subtitle",
32 | run: {
33 | size: 36,
34 | color: "#000000"
35 | },
36 | paragraph: { // 段落
37 | spacing: { // 字间距
38 | before: 500,
39 | after: 300
40 | }
41 | }
42 | },
43 | {
44 | id: "timu",
45 | name: "timu",
46 | run: {
47 | size: 24,
48 | color: "#000000"
49 | },
50 | paragraph: { // 段落
51 | spacing: { // 字间距
52 | before: 300,
53 | after: 150
54 | }
55 | }
56 | },
57 | {
58 | id: "daan",
59 | name: "daan",
60 | run: {
61 | size: 24,
62 | color: "#000000",
63 | // margin: {
64 | // top: 800,
65 | // bottom: 300
66 | // }
67 | },
68 | paragraph: { // 段落
69 | spacing: { // 字间距
70 | before: 100,
71 | after: 100
72 | }
73 | }
74 | }
75 | ]
76 | },
77 | numbering: { // 设置项目编号
78 | config: [
79 | {
80 | reference: "my-crazy-numbering",
81 | levels: [
82 | {
83 | level: 1,
84 | format: "decimal",
85 | text: "%2.",
86 | alignment: AlignmentType.LEFT,
87 | style: {
88 | paragraph: {
89 | indent: {left: 0, hanging: 360}
90 | }
91 | }
92 | },
93 | ]
94 | },
95 | {
96 | reference: "jiexi-numbering",
97 | levels: [
98 | {
99 | level: 1,
100 | format: "decimal",
101 | text: "%2.",
102 | alignment: AlignmentType.LEFT,
103 | style: {
104 | paragraph: {
105 | indent: {left: 0, hanging: 360}
106 | }
107 | }
108 | }
109 | ]
110 | }
111 | ]
112 | },
113 | sections: [
114 | {
115 | children: [
116 | new Paragraph({
117 | text: sheet.title,
118 | heading: HeadingLevel.TITLE,
119 | alignment: 'center'
120 | }),
121 | new Paragraph({
122 | text: '单项选择题',
123 | heading: 'subtitle',
124 | alignment: 'center'
125 | }),
126 | ...danxuanList.map((timu, index) => {
127 | return getTimuElement(timu)
128 | }).reduce((prev, curr) => prev.concat(curr), []),
129 | new Paragraph({
130 | text: '多项选择题',
131 | heading: 'subtitle',
132 | alignment: 'center'
133 | }),
134 | ...duoxuanList.map((timu, index) => {
135 | return getTimuElement(timu, 'duo')
136 | }).reduce((prev, curr) => prev.concat(curr), []),
137 | new Paragraph({
138 | text: '参考答案',
139 | heading: 'subtitle',
140 | alignment: 'center'
141 | }),
142 | new Paragraph({
143 | children: [
144 | new TextRun({
145 | text: '一 单项选择题',
146 | bold: true,
147 | heading: 'timu'
148 | })
149 | ]
150 | }),
151 | ...getDaanElement(danxuanList),
152 | new Paragraph({
153 | children: [
154 | new TextRun({
155 | text: '二 多项选择题',
156 | bold: true,
157 | heading: 'timu'
158 | })
159 | ]
160 | }),
161 | ...getDaanElement(duoxuanList, 'duo'),
162 | new Paragraph({
163 | text: '答案解析',
164 | heading: 'subtitle',
165 | alignment: 'center'
166 | }),
167 | new Paragraph({
168 | children: [
169 | new TextRun({
170 | text: '一 单项选择题',
171 | bold: true,
172 | heading: 'timu'
173 | })
174 | ]
175 | }),
176 | ...danxuanList.map((timu, index) => {
177 | return getJiexiElement(timu)
178 | }).reduce((prev, curr) => prev.concat(curr), []),
179 | new Paragraph({
180 | children: [
181 | new TextRun({
182 | text: '二 多项选择题',
183 | bold: true,
184 | heading: 'timu'
185 | })
186 | ]
187 | }),
188 | ...duoxuanList.map((timu, index) => {
189 | return getJiexiElement(timu, 'duo')
190 | }).reduce((prev, curr) => prev.concat(curr), []),
191 | ]
192 | }
193 | ]
194 | })
195 |
196 | return document
197 | }
198 | }
199 |
200 | function getTimuElement(timu, danOrDuo = 'dan') {
201 | const arr = []
202 |
203 | // 添加题目
204 | const p = new Paragraph({
205 | text: timu['题目'],
206 | heading: 'timu',
207 | numbering: {
208 | reference: 'my-crazy-numbering',
209 | level: 1
210 | }
211 | })
212 | arr.push(p)
213 |
214 | // 添加选项
215 | let xuanxiangMax = Math.max(...[
216 | timu['A'] && String(timu['A']).length || 0,
217 | timu['B'] && String(timu['B']).length || 0,
218 | timu['C'] && String(timu['C']).length || 0,
219 | timu['D'] && String(timu['D']).length || 0,
220 | timu['E'] && String(timu['E']).length || 0
221 | ])
222 | if (xuanxiangMax > 10) {
223 | // 换行
224 | arr.push(new Paragraph({
225 | text: `A.${timu['A']}`,
226 | heading: 'daan',
227 | }))
228 | arr.push(new Paragraph({
229 | text: `B.${timu['B']}`,
230 | heading: 'daan',
231 | }))
232 | arr.push(new Paragraph({
233 | text: `C.${timu['C']}`,
234 | heading: 'daan',
235 | }))
236 | arr.push(new Paragraph({
237 | text: `D.${timu['D']}`,
238 | heading: 'daan',
239 | }))
240 | if (danOrDuo === 'duo') {
241 | arr.push(new Paragraph({
242 | text: `E.${timu['E']}`,
243 | heading: 'daan',
244 | }))
245 | }
246 | } else {
247 | // 2个选项一排
248 | let E = []
249 | if (danOrDuo === 'duo') {
250 | E = [
251 | new TableRow({
252 | children: [
253 | new TableCell({
254 | children: [
255 | new Paragraph({
256 | text: `E.${timu['E']}`,
257 | heading: 'daan',
258 | })
259 | ]
260 | }),
261 | new TableCell({
262 | children: [
263 | new Paragraph({
264 | text: ` `,
265 | heading: 'daan',
266 | })
267 | ]
268 | })
269 | ]
270 | })
271 | ]
272 | }
273 | arr.push(new Table({
274 | borders: TableBorders.NONE,
275 | width: {
276 | type: WidthType.PERCENTAGE,
277 | size: 100
278 | },
279 | rows: [
280 | new TableRow({
281 | children: [
282 | new TableCell({
283 | children: [
284 | new Paragraph({
285 | text: `A.${timu['A']}`,
286 | heading: 'daan',
287 | }),
288 | ],
289 | }),
290 | new TableCell({
291 | children: [
292 | new Paragraph({
293 | text: `B.${timu['B']}`,
294 | heading: 'daan',
295 | }),
296 | ],
297 | })
298 | ],
299 | }),
300 | new TableRow({
301 | children: [
302 | new TableCell({
303 | children: [
304 | new Paragraph({
305 | text: `C.${timu['C']}`,
306 | heading: 'daan',
307 | }),
308 | ]
309 | }),
310 | new TableCell({
311 | children: [
312 | new Paragraph({
313 | text: `D.${timu['D']}`,
314 | heading: 'daan',
315 | })
316 | ]
317 | })
318 | ]
319 | }),
320 | ...E
321 | ],
322 | }))
323 | }
324 | return arr
325 | }
326 |
327 | function getDaanElement(list, danOrDuo = 'dan') {
328 | const arr = []
329 | const rows = []
330 | let curRow = null
331 | let count = danOrDuo === 'dan' ? 10 : 5
332 | list.map((item, index) => {
333 | if (index % count === 0) {
334 | curRow = new TableRow({
335 | children: [
336 | ]
337 | })
338 | }
339 | curRow.addCellToIndex(new TableCell({
340 | children: [
341 | new Paragraph({
342 | text: `${item['总序'] <= 9 ? ' ': ''}${item['总序']}. ${item['答案']}`,
343 | }),
344 | ]
345 | }), index % count)
346 | if (index % count === count - 1 || index === list.length - 1) {
347 | rows.push(curRow)
348 | }
349 | })
350 | let table = new Table({
351 | borders: TableBorders.NONE,
352 | width: {
353 | type: WidthType.PERCENTAGE,
354 | size: 100
355 | },
356 | rows: rows
357 | })
358 | arr.push(table)
359 | return arr
360 | }
361 |
362 |
363 | function getJiexiElement(timu, danOrDuo = 'dan') {
364 | const arr = []
365 | const p = new Paragraph({
366 | text: `【答案】 ${timu['答案']}. ${timu['答案_1']}`,
367 | heading: 'timu',
368 | numbering: {
369 | reference: 'jiexi-numbering',
370 | level: 1
371 | }
372 | })
373 | arr.push(p)
374 | const jiexi = new Paragraph({
375 | text: `【解析】 ${timu['解析']}`,
376 | heading: 'daan'
377 | })
378 | arr.push(jiexi)
379 | return arr
380 | }
381 |
--------------------------------------------------------------------------------