p-pc-ui 1.2.0 → 1.2.2

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.
@@ -10,7 +10,10 @@ interface Base {
10
10
  visibleHook?: Function,
11
11
  tooltip?: string,
12
12
  hideLabel?: boolean
13
- colon?: boolean
13
+ colon?: boolean,
14
+ labelSpan?: number,
15
+ valueSpan?: number,
16
+ labelAlign?: 'left' | 'right'
14
17
  }
15
18
 
16
19
 
@@ -21,7 +24,7 @@ export interface Input extends Base {
21
24
  }
22
25
 
23
26
  export interface InputNumber extends Base {
24
- type: 'numberInput',
27
+ type: 'number',
25
28
  prefix?: any,
26
29
  suffix?: any
27
30
  }
@@ -71,9 +74,8 @@ interface UploadBase extends Base {
71
74
 
72
75
  export interface UploadOss extends UploadBase {
73
76
  type: 'uploadOss',
74
- ossKey: string,
75
- getOssToken: Function,
76
- baseOssUrl?: string,
77
+ getOssToken: ({file_name}) => Promise<any>,
78
+ baseOssUrl: string,
77
79
  }
78
80
 
79
81
 
@@ -97,8 +99,8 @@ export interface Component extends Base {
97
99
 
98
100
  export interface Editor extends Base {
99
101
  type: 'editor',
100
- showOssUrl,
101
- uploadFunc: (file) => Promise<string>,
102
+ getOssToken: ({ file_name: string }) => Promise<any>,
103
+ baseOssUrl?: string,
102
104
  }
103
105
 
104
106
 
@@ -1,6 +1,6 @@
1
1
  <script setup lang="ts">
2
2
  import { ref, reactive, onMounted, render, onBeforeMount, useSlots, toRaw, shallowRef } from "vue";
3
- import type { FormDataItem } from "./index.d";
3
+ import type { FormDataItem } from "./index";
4
4
  import {
5
5
  Button as AButton,
6
6
  message,
@@ -32,7 +32,7 @@ interface Props {
32
32
  renderData: FormDataItem[];
33
33
  labelSpan?: number;
34
34
  valueSpan?: number;
35
- layout?: "row" | "col";
35
+ layout?: "horizontal" | "vertical" | "inline";
36
36
  initForm?: { [key: string]: any };
37
37
  requiredMark?: boolean;
38
38
  isSearchForm?: boolean;
@@ -45,7 +45,7 @@ interface Props {
45
45
  const props = withDefaults(defineProps<Props>(), {
46
46
  labelSpan: 8,
47
47
  valueSpan: 16,
48
- layout: "col",
48
+ layout: "horizontal",
49
49
  isSearchForm: false,
50
50
  requiredMark: true,
51
51
  });
@@ -80,15 +80,21 @@ const disposeRenderData = (renderData: FormDataItem[]) => {
80
80
  const _renderData = _.cloneDeep(renderData).map((val) => ({
81
81
  ...val,
82
82
  rules: [] as any,
83
- }));
83
+ })) as (FormDataItem & {rules:[]})[];
84
84
 
85
85
  for (const renderItem of _renderData) {
86
- const { fieldType, fieldRules, label } = renderItem;
86
+ let { fieldType, fieldRules, label } = renderItem;
87
87
  // 处理校验规则
88
88
  const rules: any = [];
89
89
  const operateType = ["select", "treeSeect", "date", "datePicker"].includes(renderItem.type) ? "选择" : "输入";
90
90
  for (const fieldRule of fieldRules || []) {
91
91
  const { msg, required, min, max } = fieldRule;
92
+
93
+ // 图片需要额外处理
94
+
95
+ if((renderItem.type == 'uploadOss' || renderItem.type== 'upload') && renderItem.fieldType == 'string'){
96
+ fieldType ='array'
97
+ }
92
98
 
93
99
  if (required) {
94
100
  rules.push({
@@ -155,6 +161,7 @@ const disposeRenderData = (renderData: FormDataItem[]) => {
155
161
  }
156
162
  }
157
163
  }
164
+
158
165
  return _renderData;
159
166
  };
160
167
 
@@ -183,7 +190,7 @@ const initFormState = (renderData: FormDataItem[], initFromData = {}) => {
183
190
  break;
184
191
  case "string":
185
192
  // 如果是图片类型, 并且是string类型,代表用户只需要1张图片,并且已文本的形式存放
186
- if (renderItem.type == "uploadOss") {
193
+ if (renderItem.type == "uploadOss" || renderItem.type == 'upload') {
187
194
  initValue = [];
188
195
  } else {
189
196
  initValue = "";
@@ -224,7 +231,7 @@ const initFormState = (renderData: FormDataItem[], initFromData = {}) => {
224
231
  };
225
232
  });
226
233
  } else if (renderItem.type == "editor") {
227
- initValue = initValue.replace(/\<\<图片替换地址\>\>/g, renderItem.showOssUrl);
234
+ initValue = initValue.replace(/\<\<图片替换地址\>\>/g, renderItem.baseOssUrl);
228
235
  }
229
236
 
230
237
  _formState[renderItem["key"]] = initValue;
@@ -271,9 +278,9 @@ const getFormData = async (options: { no_check?: Boolean } = {}) => {
271
278
  else if (renderItem.type == "uploadOss") {
272
279
  const fileData = toRaw(formData[key]);
273
280
  console.log("asdasdasd", fileData);
274
- const keys = fileData.map((val) => val.response.key);
281
+ const keys = fileData.map((val)=>{return val?.response?.key || val.key});
275
282
  returnFormData[key] = renderItem?.fieldType == "string" ? keys[0] : keys;
276
- }
283
+ }
277
284
  // 获取file对象
278
285
  else if (renderItem.type == "upload") {
279
286
  console.log("上传数据", formState[key]);
@@ -284,7 +291,16 @@ const getFormData = async (options: { no_check?: Boolean } = {}) => {
284
291
 
285
292
  // 处理富文本字段
286
293
  else if (renderItem.type == "editor") {
287
- returnFormData[key] = replaceUrl(returnFormData[key], renderItem.showOssUrl, "<<图片替换地址>>");
294
+ const richText = formData[key];
295
+ const dom = new DOMParser().parseFromString(richText, "text/html");
296
+ // 将视频居中展示
297
+ const videos = dom.querySelectorAll('[data-w-e-type="video"]') || [];
298
+ //@ts-ignore
299
+ for (const video of videos) {
300
+ //@ts-ignore
301
+ video.style.textAlign = "center";
302
+ }
303
+ returnFormData[key] = replaceUrl(dom.body.innerHTML, renderItem.baseOssUrl, "<<图片替换地址>>");
288
304
  }
289
305
 
290
306
  // 转换成上传对象
@@ -330,27 +346,38 @@ const uploadChange = (e, renderItem) => {
330
346
  formState[renderItem.key] = fileList;
331
347
  };
332
348
 
349
+ /**
350
+ * 上传到阿里云oss
351
+ */
352
+ const uploadOss = async (file, config) => {
353
+ const formData = new FormData();
354
+ formData.append("key", config.key); // oss 文件路径
355
+ formData.append("policy", config.policy);
356
+ formData.append("OSSAccessKeyId", config.OSSAccessKeyId);
357
+ formData.append("success_action_status", "200");
358
+ formData.append("signature", config.signature);
359
+ formData.append("file", file);
360
+ await fetch(config.host, {
361
+ method: "POST",
362
+ body: formData,
363
+ });
364
+ message.success("上传成功");
365
+
366
+ return config.key;
367
+ };
368
+
333
369
  /**
334
370
  * 自定义上传事件
335
371
  */
336
372
  const uploadRequest = async (options, renderItem: FormDataItem) => {
337
373
  const file = options.file;
338
374
  if (renderItem.type == "uploadOss") {
339
- const config: any = await renderItem.getOssToken({ type: renderItem.ossKey, file_name: file.name });
340
-
341
- const formData = new FormData();
342
- formData.append("key", config.key); // oss 文件路径
343
- formData.append("policy", config.policy);
344
- formData.append("OSSAccessKeyId", config.OSSAccessKeyId);
345
- formData.append("success_action_status", "200");
346
- formData.append("signature", config.signature);
347
- formData.append("file", file);
348
- await fetch(config.host, {
349
- method: "POST",
350
- body: formData,
351
- });
352
- message.success("上传成功");
353
- options.onSuccess({ key: config.key }, file);
375
+ const config: any = await renderItem.getOssToken({ file_name: file.name });
376
+
377
+ const key = await uploadOss(file, config);
378
+ console.log("上传结果",key)
379
+
380
+ options.onSuccess({ key }, file);
354
381
  } else {
355
382
  setTimeout(() => {
356
383
  options.onProgress({ percent: 100 });
@@ -362,6 +389,16 @@ const uploadRequest = async (options, renderItem: FormDataItem) => {
362
389
  }
363
390
  };
364
391
 
392
+ /**
393
+ * 富文本上传
394
+ */
395
+ const editorUpload = async (renderItem, file, insertFn) => {
396
+ const config: any = await renderItem.getOssToken({ type: renderItem.ossKey, file_name: file.name });
397
+ const key = await uploadOss(file, config);
398
+ console.log(insertFn, key);
399
+ insertFn(renderItem.baseOssUrl + key);
400
+ };
401
+
365
402
  const sendNoticeClick = async (renderItem) => {
366
403
  if (renderItem.sendStatus == "sending") return;
367
404
  const res = await renderItem.sendNoticeFunc();
@@ -400,13 +437,13 @@ defineExpose({
400
437
  :model="formState"
401
438
  name="basic"
402
439
  autocomplete="off"
403
- :layout="layout == 'row' ? 'inline' : 'vertical'"
440
+ :layout="layout"
404
441
  :required-mark="requiredMark"
405
442
  >
406
443
  <div v-for="(renderItem, index) in renderData">
407
444
  <a-form-item
408
- :label-col="{ span: renderItem.hideLabel ? 0 : labelSpan }"
409
- :wrapper-col="{ span: renderItem.hideLabel ? undefined : valueSpan }"
445
+ :label-col="{ span: renderItem.hideLabel ? 0 : renderItem.labelSpan || labelSpan }"
446
+ :wrapper-col="{ span: renderItem.hideLabel ? undefined : renderItem.valueSpan || valueSpan }"
410
447
  v-show="!renderItem.visibleHook || (renderItem.visibleHook && renderItem.visibleHook(formState))"
411
448
  :label="renderItem.label && !renderItem.hideLabel ? renderItem.label : ''"
412
449
  :name="renderItem.key"
@@ -421,6 +458,7 @@ defineExpose({
421
458
  marginBottom: isSearchForm ? '20px' : '0px',
422
459
  }"
423
460
  :tooltip="renderItem.tooltip"
461
+ :label-align="renderItem.labelAlign || 'right'"
424
462
  >
425
463
  <a-input
426
464
  v-model:value="formState[renderItem.key]"
@@ -494,13 +532,6 @@ defineExpose({
494
532
  :auto-size="{ minRows: 2, maxRows: 10 }"
495
533
  />
496
534
 
497
- <a-input-number
498
- style="width: 100%"
499
- v-model:value="formState[renderItem.key]"
500
- v-if="renderItem.type == 'numberInput'"
501
- :placeholder="`请输入${renderItem.label}`"
502
- />
503
-
504
535
  <a-select
505
536
  style="min-width: 170px; margin-right: 15px"
506
537
  v-model:value="formState[renderItem.key]"
@@ -575,7 +606,7 @@ defineExpose({
575
606
  style="border-bottom: 1px solid #ccc"
576
607
  :editor="editorRef"
577
608
  :defaultConfig="{
578
- excludeKeys: ['group-video', 'insertImage', 'codeBlock'],
609
+ excludeKeys: ['insertVideo', 'insertImage', 'codeBlock'],
579
610
  }"
580
611
  mode="default"
581
612
  />
@@ -586,9 +617,13 @@ defineExpose({
586
617
  placeholder: '请输入内容...',
587
618
  MENU_CONF: {
588
619
  uploadImage: {
589
- customUpload: async (file, insertImgFn) => {
590
- const url = await renderItem.uploadFunc(file);
591
- insertImgFn(url);
620
+ customUpload: async (file, insertFn) => {
621
+ await editorUpload(renderItem, file, insertFn);
622
+ },
623
+ },
624
+ uploadVideo: {
625
+ customUpload: async (file, insertFn) => {
626
+ await editorUpload(renderItem, file, insertFn);
592
627
  },
593
628
  },
594
629
  },
@@ -1,6 +1,5 @@
1
1
 
2
2
  interface TableBase {
3
- key: string;
4
3
  title: string;
5
4
  width?: number;
6
5
  sorter?: boolean;
@@ -11,6 +10,7 @@ interface TableBase {
11
10
  }
12
11
 
13
12
  interface TablePic extends TableBase {
13
+ key: string;
14
14
  type: 'pic';
15
15
  showOssUrlFunc?: (ossKey: string) => string;
16
16
  picWidth?: number;
@@ -18,21 +18,23 @@ interface TablePic extends TableBase {
18
18
  }
19
19
 
20
20
  interface TableLink extends TableBase {
21
+ key: string;
21
22
  type: 'link';
22
23
  }
23
24
 
24
25
  interface TableCommon extends TableBase {
25
- type?: 'common';
26
+ key: string;
27
+ type: 'common';
26
28
  }
27
29
 
28
30
  interface TableDate extends TableBase {
31
+ key: string;
29
32
  type: 'date';
30
33
  format?: string;
31
34
  }
32
35
 
33
36
  interface TableOperate extends TableBase {
34
37
  type: 'operate',
35
- key?: string,
36
38
  operateButtons: { label: string; click: Function; visibleFunc?: Function }[];
37
39
 
38
40
  }
@@ -1,4 +1,3 @@
1
-
2
1
  <script lang="ts" setup>
3
2
  // import "viewerjs/dist/viewer.css";
4
3
  import { api as viewerApi } from "v-viewer";
@@ -6,6 +5,7 @@ import PForm from "../p-form/p-form.vue";
6
5
  import { h, ref, reactive, onMounted, toRaw } from "vue";
7
6
  import * as _ from "../../utils/dataUtils";
8
7
  import dayjs from "dayjs";
8
+ import { Table as ATable, Button as AButton } from "ant-design-vue";
9
9
  import type { FormDataItem } from "../p-form/index.d";
10
10
  import type { TableColumn } from "./index.d";
11
11
  const SearchFormRef = ref();
@@ -236,7 +236,7 @@ defineExpose({
236
236
  :is-search-form="true"
237
237
  :render-data="searchRenderData"
238
238
  :init-form="initSearchFormData"
239
- layout="row"
239
+ layout="inline"
240
240
  >
241
241
  <template v-slot:button>
242
242
  <a-button type="primary" @click="searchClick" style="margin-left: 20px"> 搜索 </a-button>
@@ -269,11 +269,13 @@ defineExpose({
269
269
  }"
270
270
  bordered
271
271
  @change="onchange"
272
- ></a-table>
272
+ >
273
+ <template #bodyCell="slotProps">
274
+ <slot name="bodyCell" v-bind="slotProps" />
275
+ </template>
276
+ </a-table>
273
277
  </template>
274
278
 
275
-
276
-
277
279
  <style>
278
280
  .ant-table-striped :deep(.table-striped) td {
279
281
  background-color: #fafafa;
package/dist/index.ts CHANGED
@@ -1,4 +1,4 @@
1
- import PTable from './components/p-table'
1
+ import PTable from './components/p-table/p-table.vue'
2
2
  import PForm from './components/p-form/p-form.vue'
3
3
  import PModalForm from './components/p-modal-form/p-modal-form.vue'
4
4
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "p-pc-ui",
3
- "version": "1.2.0",
3
+ "version": "1.2.2",
4
4
  "type": "module",
5
5
  "module": "dist/index.ts",
6
6
  "main": "dist/index.ts",
@@ -1,8 +0,0 @@
1
-
2
- import type { App } from 'vue'
3
- import PTable from './p-table.vue'
4
- PTable.install = (app: App) => {
5
- app.component('PTable', PTable)
6
- }
7
-
8
- export default PTable