n20-project-component 1.0.1 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,65 +1,69 @@
1
- {
2
- "name": "n20-project-component",
3
- "version": "1.0.1",
4
- "description": "PC 端 Vue 2 + Element UI 组件库",
5
- "main": "dist/n20-project-component.umd.min.js",
6
- "module": "dist/n20-project-component.common.js",
7
- "style": "dist/n20-project-component.css",
8
- "files": [
9
- "dist",
10
- "src",
11
- "README.md"
12
- ],
13
- "scripts": {
14
- "dev": "vue-cli-service serve --open",
15
- "build": "vue-cli-service build --target lib --name n20-project-component src/index.js",
16
- "lint": "vue-cli-service lint",
17
- "prepublishOnly": "npm run build"
18
- },
19
- "peerDependencies": {
20
- "vue": "^2.6.0",
21
- "element-ui": "^2.15.0"
22
- },
23
- "dependencies": {},
24
- "devDependencies": {
25
- "@vue/cli-plugin-babel": "~4.5.0",
26
- "@vue/cli-plugin-eslint": "~4.5.0",
27
- "@vue/cli-service": "~4.5.0",
28
- "babel-eslint": "^10.1.0",
29
- "core-js": "^3.6.5",
30
- "element-ui": "^2.15.14",
31
- "eslint": "^6.7.2",
32
- "eslint-plugin-vue": "^6.2.2",
33
- "sass": "1.26.2",
34
- "sass-loader": "8.0.2",
35
- "vue": "^2.6.11",
36
- "vue-template-compiler": "^2.6.11"
37
- },
38
- "eslintConfig": {
39
- "root": true,
40
- "env": {
41
- "node": true
42
- },
43
- "extends": [
44
- "plugin:vue/essential",
45
- "eslint:recommended"
46
- ],
47
- "parserOptions": {
48
- "parser": "babel-eslint"
49
- },
50
- "rules": {}
51
- },
52
- "browserslist": [
53
- "> 1%",
54
- "last 2 versions",
55
- "not dead"
56
- ],
57
- "keywords": [
58
- "vue2",
59
- "element-ui",
60
- "component-library",
61
- "n20"
62
- ],
63
- "author": "",
64
- "license": "MIT"
65
- }
1
+ {
2
+ "name": "n20-project-component",
3
+ "version": "1.0.5",
4
+ "description": "PC 端 Vue 2 + Element UI 组件库",
5
+ "main": "dist/n20-project-component.umd.min.js",
6
+ "module": "dist/n20-project-component.common.js",
7
+ "style": "dist/n20-project-component.css",
8
+ "files": [
9
+ "dist",
10
+ "src",
11
+ "README.md"
12
+ ],
13
+ "scripts": {
14
+ "dev": "vue-cli-service serve --open",
15
+ "build": "vue-cli-service build --target lib --name n20-project-component src/index.js",
16
+ "lint": "vue-cli-service lint",
17
+ "prepublishOnly": "npm run build"
18
+ },
19
+ "peerDependencies": {
20
+ "vue": "^2.6.0",
21
+ "element-ui": "^2.15.0"
22
+ },
23
+ "dependencies": {
24
+ "n20-common-lib": "^2.22.39"
25
+ },
26
+ "devDependencies": {
27
+ "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6",
28
+ "@babel/plugin-proposal-optional-chaining": "^7.21.0",
29
+ "@vue/cli-plugin-babel": "~4.5.0",
30
+ "@vue/cli-plugin-eslint": "~4.5.0",
31
+ "@vue/cli-service": "~4.5.0",
32
+ "babel-eslint": "^10.1.0",
33
+ "core-js": "^3.6.5",
34
+ "element-ui": "^2.15.14",
35
+ "eslint": "^6.7.2",
36
+ "eslint-plugin-vue": "^6.2.2",
37
+ "sass": "1.26.2",
38
+ "sass-loader": "8.0.2",
39
+ "vue": "^2.6.11",
40
+ "vue-template-compiler": "^2.6.11"
41
+ },
42
+ "eslintConfig": {
43
+ "root": true,
44
+ "env": {
45
+ "node": true
46
+ },
47
+ "extends": [
48
+ "plugin:vue/essential",
49
+ "eslint:recommended"
50
+ ],
51
+ "parserOptions": {
52
+ "parser": "babel-eslint"
53
+ },
54
+ "rules": {}
55
+ },
56
+ "browserslist": [
57
+ "> 1%",
58
+ "last 2 versions",
59
+ "not dead"
60
+ ],
61
+ "keywords": [
62
+ "vue2",
63
+ "element-ui",
64
+ "component-library",
65
+ "n20"
66
+ ],
67
+ "author": "",
68
+ "license": "MIT"
69
+ }
@@ -1,74 +1,74 @@
1
- <template>
2
- <el-button
3
- :type="type"
4
- :size="size"
5
- :disabled="disabled"
6
- :loading="loading"
7
- :icon="icon"
8
- class="n20-demo-button"
9
- @click="handleClick"
10
- >
11
- <slot>{{ text }}</slot>
12
- </el-button>
13
- </template>
14
-
15
- <script>
16
- /**
17
- * DemoButton - 示例按钮组件
18
- *
19
- * 用于验证组件库构建流程。实际开发时可删除此组件,替换为业务组件。
20
- *
21
- * @example
22
- * <DemoButton type="primary" text="提交" @click="handleSubmit" />
23
- */
24
- export default {
25
- name: 'N20DemoButton',
26
- props: {
27
- /** 按钮文本 */
28
- text: {
29
- type: String,
30
- default: '按钮',
31
- },
32
- /** 按钮类型:primary / success / warning / danger / info / text */
33
- type: {
34
- type: String,
35
- default: 'primary',
36
- },
37
- /** 按钮尺寸:medium / small / mini */
38
- size: {
39
- type: String,
40
- default: '',
41
- },
42
- /** 是否禁用 */
43
- disabled: {
44
- type: Boolean,
45
- default: false,
46
- },
47
- /** 是否加载中 */
48
- loading: {
49
- type: Boolean,
50
- default: false,
51
- },
52
- /** 图标类名 */
53
- icon: {
54
- type: String,
55
- default: '',
56
- },
57
- },
58
- methods: {
59
- handleClick(e) {
60
- this.$emit('click', e)
61
- },
62
- },
63
- }
64
- </script>
65
-
66
- <style lang="scss" scoped>
67
- @import '~@/styles/variables.scss';
68
-
69
- .n20-demo-button {
70
- // 自定义样式示例 —— 在 Element UI 基础上扩展
71
- border-radius: $--n20-border-radius;
72
- font-size: $--n20-font-size-base;
73
- }
74
- </style>
1
+ <template>
2
+ <el-button
3
+ :type="type"
4
+ :size="size"
5
+ :disabled="disabled"
6
+ :loading="loading"
7
+ :icon="icon"
8
+ class="n20-demo-button"
9
+ @click="handleClick"
10
+ >
11
+ <slot>{{ text }}</slot>
12
+ </el-button>
13
+ </template>
14
+
15
+ <script>
16
+ /**
17
+ * DemoButton - 示例按钮组件
18
+ *
19
+ * 用于验证组件库构建流程。实际开发时可删除此组件,替换为业务组件。
20
+ *
21
+ * @example
22
+ * <DemoButton type="primary" text="提交" @click="handleSubmit" />
23
+ */
24
+ export default {
25
+ name: 'N20DemoButton',
26
+ props: {
27
+ /** 按钮文本 */
28
+ text: {
29
+ type: String,
30
+ default: '按钮',
31
+ },
32
+ /** 按钮类型:primary / success / warning / danger / info / text */
33
+ type: {
34
+ type: String,
35
+ default: 'primary',
36
+ },
37
+ /** 按钮尺寸:medium / small / mini */
38
+ size: {
39
+ type: String,
40
+ default: '',
41
+ },
42
+ /** 是否禁用 */
43
+ disabled: {
44
+ type: Boolean,
45
+ default: false,
46
+ },
47
+ /** 是否加载中 */
48
+ loading: {
49
+ type: Boolean,
50
+ default: false,
51
+ },
52
+ /** 图标类名 */
53
+ icon: {
54
+ type: String,
55
+ default: '',
56
+ },
57
+ },
58
+ methods: {
59
+ handleClick(e) {
60
+ this.$emit('click', e)
61
+ },
62
+ },
63
+ }
64
+ </script>
65
+
66
+ <style lang="scss" scoped>
67
+ @import '~@/styles/variables.scss';
68
+
69
+ .n20-demo-button {
70
+ // 自定义样式示例 —— 在 Element UI 基础上扩展
71
+ border-radius: $--n20-border-radius;
72
+ font-size: $--n20-font-size-base;
73
+ }
74
+ </style>
@@ -0,0 +1,237 @@
1
+ <template>
2
+ <div class="n20-batch-input">
3
+ <el-input
4
+ :value="displayValue"
5
+ :placeholder="placeholder"
6
+ :disabled="disabled"
7
+ readonly
8
+ class="n20-batch-input__trigger"
9
+ @click.native="handleOpen"
10
+ >
11
+ <template slot="suffix">
12
+ <span class="n20-batch-input__suffix">
13
+ <i
14
+ v-if="value && !disabled"
15
+ class="el-icon-circle-close n20-batch-input__clear"
16
+ @click.stop="handleClear"
17
+ />
18
+ <i
19
+ class="el-icon-edit-outline n20-batch-input__edit"
20
+ @click.stop="handleOpen"
21
+ />
22
+ </span>
23
+ </template>
24
+ </el-input>
25
+
26
+ <el-dialog
27
+ :title="dialogTitle"
28
+ :visible.sync="dialogVisible"
29
+ width="520px"
30
+ :close-on-click-modal="false"
31
+ @open="handleDialogOpen"
32
+ @closed="handleDialogClosed"
33
+ >
34
+ <div class="n20-batch-input__body">
35
+ <el-input
36
+ v-model="draftText"
37
+ type="textarea"
38
+ :rows="10"
39
+ :placeholder="textareaPlaceholder"
40
+ @input="handleTextareaInput"
41
+ />
42
+ <div
43
+ class="n20-batch-input__counter"
44
+ :class="{ 'is-over': isOverLimit }"
45
+ >
46
+ <span v-if="isOverLimit" class="n20-batch-input__error">
47
+ 已超出最大条数 {{ max }},请删减后提交
48
+ </span>
49
+ <span class="n20-batch-input__count">
50
+ 当前 {{ parsedItems.length }} 条 / 最大 {{ max }} 条
51
+ </span>
52
+ </div>
53
+ </div>
54
+ <div slot="footer">
55
+ <el-button @click="dialogVisible = false">取 消</el-button>
56
+ <el-button
57
+ type="primary"
58
+ :disabled="isOverLimit"
59
+ @click="handleConfirm"
60
+ >
61
+ 确 认
62
+ </el-button>
63
+ </div>
64
+ </el-dialog>
65
+ </div>
66
+ </template>
67
+
68
+ <script>
69
+ /**
70
+ * N20BatchInput - 批量输入组件
71
+ *
72
+ * 点击输入框打开弹窗,支持从 Excel 粘贴内容,自动按换行/制表符/逗号拆分为多个条目。
73
+ * v-model 绑定逗号分隔的字符串。
74
+ *
75
+ * @example
76
+ * <N20BatchInput v-model="batchValue" :max="50" />
77
+ */
78
+ export default {
79
+ name: 'N20BatchInput',
80
+ model: {
81
+ prop: 'value',
82
+ event: 'input',
83
+ },
84
+ props: {
85
+ /** v-model 绑定值,逗号分隔字符串 */
86
+ value: {
87
+ type: String,
88
+ default: '',
89
+ },
90
+ /** 最大条数限制 */
91
+ max: {
92
+ type: Number,
93
+ default: 100,
94
+ },
95
+ /** 输入框占位符 */
96
+ placeholder: {
97
+ type: String,
98
+ default: '请输入',
99
+ },
100
+ /** 弹窗标题 */
101
+ dialogTitle: {
102
+ type: String,
103
+ default: '批量输入',
104
+ },
105
+ /** 文本域占位符 */
106
+ textareaPlaceholder: {
107
+ type: String,
108
+ default: '支持从 Excel 粘贴,每行 / 逗号 / Tab 自动识别为一条',
109
+ },
110
+ /** 是否禁用 */
111
+ disabled: {
112
+ type: Boolean,
113
+ default: false,
114
+ },
115
+ },
116
+ data() {
117
+ return {
118
+ dialogVisible: false,
119
+ draftText: '',
120
+ parsedItems: [],
121
+ }
122
+ },
123
+ computed: {
124
+ displayValue() {
125
+ return this.value || ''
126
+ },
127
+ isOverLimit() {
128
+ return this.parsedItems.length > this.max
129
+ },
130
+ },
131
+ methods: {
132
+ handleOpen() {
133
+ if (this.disabled) return
134
+ this.dialogVisible = true
135
+ },
136
+ handleDialogOpen() {
137
+ // 将当前 value 还原为每行一条
138
+ if (this.value) {
139
+ const items = this.value.split(',').map(s => s.trim()).filter(Boolean)
140
+ this.draftText = items.join('\n')
141
+ this.parsedItems = items
142
+ } else {
143
+ this.draftText = ''
144
+ this.parsedItems = []
145
+ }
146
+ },
147
+ handleDialogClosed() {
148
+ this.draftText = ''
149
+ this.parsedItems = []
150
+ },
151
+ handleTextareaInput(val) {
152
+ const items = val
153
+ .split(/[\n\r\t,,]+/)
154
+ .map(s => s.trim())
155
+ .filter(Boolean)
156
+ this.parsedItems = items
157
+ },
158
+ handleConfirm() {
159
+ if (this.isOverLimit) return
160
+ const result = this.parsedItems.join(',')
161
+ this.$emit('input', result)
162
+ this.$emit('change', result)
163
+ this.dialogVisible = false
164
+ },
165
+ handleClear() {
166
+ this.$emit('input', '')
167
+ this.$emit('change', '')
168
+ },
169
+ },
170
+ }
171
+ </script>
172
+
173
+ <style scoped>
174
+ .n20-batch-input {
175
+ display: inline-block;
176
+ width: 100%;
177
+ }
178
+
179
+ .n20-batch-input__trigger {
180
+ cursor: pointer;
181
+ }
182
+
183
+ .n20-batch-input__trigger /deep/ .el-input__inner {
184
+ cursor: pointer;
185
+ overflow: hidden;
186
+ text-overflow: ellipsis;
187
+ white-space: nowrap;
188
+ padding-right: 52px;
189
+ }
190
+
191
+ .n20-batch-input__suffix {
192
+ display: inline-flex;
193
+ align-items: center;
194
+ height: 100%;
195
+ gap: 4px;
196
+ }
197
+
198
+ .n20-batch-input__clear:hover {
199
+ color: #909399;
200
+ }
201
+
202
+ .n20-batch-input__edit {
203
+ color: #c0c4cc;
204
+ cursor: pointer;
205
+ }
206
+
207
+ .n20-batch-input__edit:hover {
208
+ color: #409eff;
209
+ }
210
+
211
+ .n20-batch-input__body {
212
+ padding: 0 4px;
213
+ }
214
+
215
+ .n20-batch-input__counter {
216
+ display: flex;
217
+ justify-content: flex-end;
218
+ align-items: center;
219
+ margin-top: 8px;
220
+ font-size: 13px;
221
+ color: #909399;
222
+ gap: 12px;
223
+ }
224
+
225
+ .n20-batch-input__counter.is-over {
226
+ color: #f56c6c;
227
+ }
228
+
229
+ .n20-batch-input__error {
230
+ flex: 1;
231
+ color: #f56c6c;
232
+ }
233
+
234
+ .n20-batch-input__count {
235
+ white-space: nowrap;
236
+ }
237
+ </style>