@titaui/pc 1.7.21 → 1.7.25

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.
Files changed (96) hide show
  1. package/lib/components/button/text-btn/index.css +1 -0
  2. package/lib/components/button/text-btn/index.js +10 -12
  3. package/lib/components/cascader/index.css +38 -11
  4. package/lib/components/cascader/index.js +10 -5
  5. package/lib/components/cascader/time.js +31 -0
  6. package/lib/components/common-share/index.css +223 -0
  7. package/lib/components/common-share/index.js +104 -0
  8. package/lib/components/common-share/publishMblog.js +155 -0
  9. package/lib/components/common-share/request-apis.js +56 -0
  10. package/lib/components/common-share/types.js +5 -0
  11. package/lib/components/follower-visitor/index.css +8 -3
  12. package/lib/components/form/form-fields/group/index.js +2 -1
  13. package/lib/components/menus/components/menu-tree/tree-node/index.css +9 -6
  14. package/lib/components/okr-detail/components/okr-tree/tree-node/e-node/e-project.js +4 -2
  15. package/lib/components/okr-detail/components/okr-tree/tree-node/e-node/e-task-level2.js +2 -2
  16. package/lib/components/okr-detail/components/okr-tree/tree-node/e-node/e-task.js +2 -2
  17. package/lib/components/scrollbar/index.js +13 -3
  18. package/lib/components/select-tags/index.css +28 -18
  19. package/lib/components/select-tags/index.js +2 -2
  20. package/lib/components/weekly-report/board.js +43 -0
  21. package/lib/components/weekly-report/card.js +235 -0
  22. package/lib/components/weekly-report/common-painter/darwAvatar.js +157 -0
  23. package/lib/components/weekly-report/common-painter/drawName.js +59 -0
  24. package/lib/components/weekly-report/common-painter/openDataPainter.js +95 -0
  25. package/lib/components/weekly-report/common-painter/setSize.js +19 -0
  26. package/lib/components/weekly-report/common-painter/utils.js +85 -0
  27. package/lib/components/weekly-report/img/body.png +0 -0
  28. package/lib/components/weekly-report/img/bofang.png +0 -0
  29. package/lib/components/weekly-report/img/bottom.png +0 -0
  30. package/lib/components/weekly-report/img/communication.png +0 -0
  31. package/lib/components/weekly-report/img/down.png +0 -0
  32. package/lib/components/weekly-report/img/finish.png +0 -0
  33. package/lib/components/weekly-report/img/laba.png +0 -0
  34. package/lib/components/weekly-report/img/praise.png +0 -0
  35. package/lib/components/weekly-report/img/quote.png +0 -0
  36. package/lib/components/weekly-report/img/title.png +0 -0
  37. package/lib/components/weekly-report/img/triangle-pop.png +0 -0
  38. package/lib/components/weekly-report/img/up.png +0 -0
  39. package/lib/components/weekly-report/index.css +332 -0
  40. package/lib/components/weekly-report/index.js +134 -0
  41. package/lib/components/weekly-report/statistics.js +47 -0
  42. package/lib/index.js +8 -0
  43. package/lib/pages/aha2021/index.css +0 -1
  44. package/lib/pages/new-okr-list/header/filter.js +51 -2
  45. package/lib/pages/new-okr-list/index.js +44 -5
  46. package/lib/utils/helpers.js +8 -1
  47. package/package.json +1 -1
  48. package/src/components/button/text-btn/index.scss +1 -0
  49. package/src/components/button/text-btn/index.tsx +13 -13
  50. package/src/components/button/types.ts +1 -0
  51. package/src/components/cascader/index.scss +50 -27
  52. package/src/components/cascader/index.tsx +18 -16
  53. package/src/components/cascader/time.js +13 -0
  54. package/src/components/common-share/index.scss +199 -0
  55. package/src/components/common-share/index.tsx +91 -0
  56. package/src/components/common-share/publishMblog.tsx +79 -0
  57. package/src/components/common-share/request-apis.js +37 -0
  58. package/src/components/common-share/types.ts +4 -0
  59. package/src/components/follower-visitor/index.scss +9 -4
  60. package/src/components/form/form-fields/group/index.tsx +3 -3
  61. package/src/components/menus/components/menu-tree/tree-node/index.scss +2 -1
  62. package/src/components/okr-detail/components/okr-tree/tree-node/e-node/e-project.js +1 -1
  63. package/src/components/okr-detail/components/okr-tree/tree-node/e-node/e-task-level2.js +2 -2
  64. package/src/components/okr-detail/components/okr-tree/tree-node/e-node/e-task.js +2 -2
  65. package/src/components/okr-share/index.tsx +4 -17
  66. package/src/components/scrollbar/index.tsx +2 -1
  67. package/src/components/select-tags/index.scss +9 -1
  68. package/src/components/select-tags/index.tsx +8 -12
  69. package/src/components/weekly-report/board.tsx +25 -0
  70. package/src/components/weekly-report/card.tsx +125 -0
  71. package/src/components/weekly-report/common-painter/darwAvatar.ts +81 -0
  72. package/src/components/weekly-report/common-painter/drawName.ts +19 -0
  73. package/src/components/weekly-report/common-painter/openDataPainter.ts +47 -0
  74. package/src/components/weekly-report/common-painter/setSize.ts +12 -0
  75. package/src/components/weekly-report/common-painter/utils.ts +83 -0
  76. package/src/components/weekly-report/img/body.png +0 -0
  77. package/src/components/weekly-report/img/bofang.png +0 -0
  78. package/src/components/weekly-report/img/bottom.png +0 -0
  79. package/src/components/weekly-report/img/communication.png +0 -0
  80. package/src/components/weekly-report/img/down.png +0 -0
  81. package/src/components/weekly-report/img/finish.png +0 -0
  82. package/src/components/weekly-report/img/laba.png +0 -0
  83. package/src/components/weekly-report/img/praise.png +0 -0
  84. package/src/components/weekly-report/img/quote.png +0 -0
  85. package/src/components/weekly-report/img/title.png +0 -0
  86. package/src/components/weekly-report/img/triangle-pop.png +0 -0
  87. package/src/components/weekly-report/img/up.png +0 -0
  88. package/src/components/weekly-report/index.scss +299 -0
  89. package/src/components/weekly-report/index.tsx +51 -0
  90. package/src/components/weekly-report/statistics.tsx +28 -0
  91. package/src/index.d.ts +2 -1
  92. package/src/index.js +2 -1
  93. package/src/pages/aha2021/index.scss +0 -1
  94. package/src/pages/new-okr-list/header/filter.tsx +35 -4
  95. package/src/pages/new-okr-list/index.tsx +33 -5
  96. package/src/utils/helpers.ts +4 -1
@@ -11,6 +11,7 @@ interface IProps {
11
11
  require?: boolean;
12
12
  width?: number;
13
13
  children?: ReactElement;
14
+ className?: any;
14
15
  direction?: "horizontal" | "vertical";
15
16
  }
16
17
 
@@ -18,15 +19,14 @@ const FieldGroup = (props: IProps, ref) => {
18
19
  const {
19
20
  label = "",
20
21
  direction = "vertical",
21
- // onChange,
22
- // values,
22
+ className,
23
23
  children,
24
24
  } = props;
25
25
 
26
26
  useImperativeHandle(ref, () => ({}));
27
27
 
28
28
  return (
29
- <div className={classNames(precls, `${precls}--${direction}`)}>
29
+ <div className={classNames(precls,className, `${precls}--${direction}`)}>
30
30
  <div className={`${precls}__label`}>{label}</div>
31
31
  <div className={`${precls}__content`}>
32
32
  {React.Children.map(children, (child) => {
@@ -19,6 +19,7 @@
19
19
  &-indent {
20
20
  display: inline-block;
21
21
  width: 16px;
22
+ min-width: 16px;
22
23
  }
23
24
  &-title {
24
25
  font-size: 14px;
@@ -36,7 +37,7 @@
36
37
  font-size: 14px;
37
38
  line-height: 22px;
38
39
  color: #141c28;
39
- font-weight: 500;
40
+ font-weight: 600;
40
41
  }
41
42
  }
42
43
 
@@ -70,7 +70,7 @@ export default props => {
70
70
 
71
71
  <span className={classNames(`${preCls}__e-project-node-actions-user`)}>
72
72
  {/* <TextAvatar name={user.name} id={user.userId} width={76} editable onEditUser={onEditUserHandler} /> */}
73
- <Avatar.Text name={data.principalUser.name} id={data.principalUser.userId} width={64} extraCls={isGray&&`${preCls}__e-project-node-gray`} />
73
+ <Avatar.Text name={data?.principalUser?.name} id={data?.principalUser?.userId} width={64} extraCls={isGray&&`${preCls}__e-project-node-gray`} />
74
74
  </span>
75
75
 
76
76
  <span className={classNames(`${preCls}__e-project-node-actions-date`)}>
@@ -218,8 +218,8 @@ export default (props) => {
218
218
  className={classNames(`${preCls}__e-task-level2-node-actions-user`)}
219
219
  >
220
220
  <Avatar.Text
221
- name={user.name}
222
- id={user.userId}
221
+ name={user?.name}
222
+ id={user?.userId}
223
223
  width={64}
224
224
  editable={hasAuth}
225
225
  onEditUser={onEditUserHandler}
@@ -219,8 +219,8 @@ export default (props) => {
219
219
  <span className={classNames(`${preCls}__e-task-node-actions`)}>
220
220
  <span className={classNames(`${preCls}__e-task-node-actions-user`)}>
221
221
  <Avatar.Text
222
- name={user.name}
223
- id={user.userId}
222
+ name={user?.name}
223
+ id={user?.userId}
224
224
  width={64}
225
225
  editable={hasEditAuth}
226
226
  onEditUser={onEditUserHandler}
@@ -8,7 +8,7 @@ import './index.scss';
8
8
  interface Props {
9
9
  closeModal: Function;
10
10
  getModalRef: Function;
11
- data: ShareData;
11
+ data: any;
12
12
  }
13
13
 
14
14
  const ShareContent = function({ closeModal, getModalRef, data }: Props) {
@@ -41,23 +41,10 @@ const ShareContent = function({ closeModal, getModalRef, data }: Props) {
41
41
  </Queue>
42
42
  );
43
43
  };
44
- export interface ShareData {
45
- okrName: string;
46
- okrId: number;
47
- krs: string[];
48
- user: {
49
- name: string;
50
- userId: number;
51
- departmentName: string;
52
- departmentId: number;
53
- avatar: {
54
- color: string;
55
- src?: string;
56
- };
57
- };
58
- }
44
+
59
45
  interface ShareProps {
60
- data: ShareData;
46
+ shareComponent
47
+ data: any;
61
48
  visible:boolean;
62
49
  onClose: () => void
63
50
  }
@@ -11,13 +11,14 @@ interface Props {
11
11
  }
12
12
 
13
13
  export default (props: Props) => {
14
- const { children, style } = props;
14
+ const { children, style,...restProps } = props;
15
15
 
16
16
  // @ts-ignore
17
17
  return <SimpleBar
18
18
  className={classNames(preCls)}
19
19
  timeout={800}
20
20
  style={style}
21
+ {...restProps}
21
22
  >
22
23
  {children}
23
24
  </SimpleBar>
@@ -1,4 +1,6 @@
1
- .titaui-select {
1
+ .titaui-select-tags {
2
+ display: flex;
3
+
2
4
  .rc-select-single:not(.rc-select-customize-input) .rc-select-selector {
3
5
  border: 1px solid #DFE3EA;
4
6
  }
@@ -18,6 +20,10 @@
18
20
  display: none;
19
21
  }
20
22
 
23
+ .rc-select-multiple .rc-select-selector .rc-select-selection-overflow {
24
+ overflow: hidden;
25
+ }
26
+
21
27
  .rc-select-single:not(.rc-select-customize-input) .rc-select-selector .rc-select-selection-search-input {
22
28
  display: none;
23
29
  }
@@ -46,6 +52,8 @@
46
52
  height: unset;
47
53
  padding: 7px 12px 0;
48
54
  border: 1px solid #DFE3EA;
55
+ max-height: 116px;
56
+ overflow: auto;
49
57
  }
50
58
 
51
59
  .rc-select-multiple .rc-select-selector .rc-select-selection-overflow-item {
@@ -1,4 +1,4 @@
1
- import React, { FC, useState, useEffect, useRef } from "react";
1
+ import React, { FC, useState } from "react";
2
2
  import Select, { Option } from "rc-select";
3
3
  import classNames from "classnames";
4
4
  import "rc-select/assets/index.less";
@@ -11,7 +11,7 @@ interface DataProps {
11
11
 
12
12
  interface Props {
13
13
  data: DataProps[];
14
- name?:any;
14
+ name?: any;
15
15
  selected: any;
16
16
  onChange: Function;
17
17
  mode?: any | "single" | "multiple";
@@ -19,10 +19,10 @@ interface Props {
19
19
  placeholder?: string;
20
20
  className?: any;
21
21
  noBorder?: boolean;
22
- suffix?:string;
22
+ suffix?: string;
23
23
  }
24
24
 
25
- const preCls = "titaui-select";
25
+ const preCls = "titaui-select-tags";
26
26
 
27
27
  const SelectTags: FC<Props> = ({
28
28
  selected = [],
@@ -31,26 +31,23 @@ const SelectTags: FC<Props> = ({
31
31
  style = { width: "200px" },
32
32
  mode = "single",
33
33
  className,
34
- placeholder='请选择',
34
+ placeholder = "请选择",
35
35
  name,
36
36
  noBorder,
37
37
  ...restProps
38
38
  }) => {
39
-
40
39
  const [value, setValue] = useState(selected);
41
40
 
42
41
  const onhandleChange = (value, options) => {
43
- onChange && onChange(value, options,name);
42
+ onChange && onChange(value, options, name);
44
43
  setValue(value);
45
44
  };
46
45
 
47
46
  return (
48
47
  <div className={preCls}>
49
48
  <Select
50
- className={classNames(className,{[`${preCls}-noborder`]: noBorder},)}
51
- dropdownClassName={classNames(
52
- `titaui-dropDown`,
53
- {
49
+ className={classNames(className, { [`${preCls}-noborder`]: noBorder })}
50
+ dropdownClassName={classNames(`titaui-dropDown`, {
54
51
  [`${preCls}-hasSelectItem`]: mode === "multiple",
55
52
  })}
56
53
  value={value}
@@ -75,7 +72,6 @@ const SelectTags: FC<Props> = ({
75
72
  })}
76
73
  </Select>
77
74
  </div>
78
-
79
75
  );
80
76
  };
81
77
 
@@ -0,0 +1,25 @@
1
+ import React, { ReactElement } from 'react'
2
+
3
+ interface Props {
4
+ percent: number
5
+ }
6
+ const preCls = 'weekly-report-card-board'
7
+
8
+ function Board({percent}: Props): ReactElement {
9
+ return (
10
+ <div className={preCls}>
11
+ <div className={preCls+'__done'}>
12
+ <div className={preCls+'__undone'}style={{transform:`rotate(${percent/100 * 180}deg)`}}/>
13
+ <div className={preCls+'__space'} style={{transform:'rotate(45deg)'}}/>
14
+ <div className={preCls+'__space'} />
15
+ <div className={preCls+'__space'} style={{transform:'rotate(-45deg)'}}/>
16
+ </div>
17
+
18
+ <div className={preCls+'__center'}>
19
+ <div>{percent}%</div>
20
+ </div>
21
+ </div>
22
+ )
23
+ }
24
+
25
+ export default Board
@@ -0,0 +1,125 @@
1
+ import React, { forwardRef, ReactElement, useEffect, useImperativeHandle, useRef, useState } from 'react';
2
+ import html2Canvas from 'html2canvas'
3
+ import Board from './board';
4
+ import { getLoginUserInfo } from '../../utils/helpers';
5
+ import { drawAvatar } from './common-painter/darwAvatar';
6
+ import drawName from './common-painter/drawName';
7
+ import Statistics from './statistics';
8
+ import {isWx} from '../../utils/bs-global'
9
+ import './index.scss';
10
+ import { rpost } from '../../utils/request';
11
+
12
+ const preCls = 'weekly-report-card';
13
+
14
+ interface Props {}
15
+ const getImageBase64ByUrl = toUserId => {
16
+ return rpost('v1')(`okr/share/getBase64Str`, { toUserId })
17
+ .then(getBase64Str => {
18
+ return getBase64Str.Data;
19
+ })
20
+ }
21
+ function Card({}: Props,ref): ReactElement {
22
+ const [avatarSrc, setAvatarSrc] = useState<string>();
23
+ const [nameSrc,setNameSrc] = useState<string>()
24
+ const loginUserInfo = getLoginUserInfo();
25
+ const cardRef = useRef()
26
+ useImperativeHandle(ref,()=>({
27
+ getImage: async function(){
28
+ return new Promise(res => {
29
+ let shareContent = cardRef.current, //需要截图的包裹的(原生的)DOM 对象
30
+ // @ts-ignore
31
+ width = 375, //获取dom 宽度
32
+ // @ts-ignore
33
+ height = 710, //获取dom 高度
34
+ canvas = document.createElement("canvas"), //创建一个canvas节点
35
+ scale = 2; //定义任意放大倍数 支持小数
36
+ canvas.width = width * scale; //定义canvas 宽度 * 缩放
37
+ canvas.height = height * scale; //定义canvas高度 *缩放
38
+ // @ts-ignore
39
+ canvas.style.width = width + "px";
40
+ // @ts-ignore
41
+ canvas.style.height = height + "px";
42
+ // @ts-ignore
43
+ let opts = {
44
+ backgroundColor: null, // 背景透明
45
+ scale: scale, // 添加的scale 参数
46
+ canvas: canvas, // 自定义 canvas
47
+ logging: false, // 日志开关,便于查看html2canvas的内部执行流程
48
+ width: width, // dom 原始宽度
49
+ height: height,
50
+ useCORS: true // 【重要】开启跨域配置
51
+ }
52
+ html2Canvas(cardRef.current as any, opts).then(canvas => {
53
+ let imgUrl = canvas.toDataURL('image/png'); //得到图片的base64编码数据
54
+ res(imgUrl)
55
+ })
56
+ })
57
+
58
+ }
59
+ }),[])
60
+ useEffect(() => {
61
+ if (isWx()) {
62
+ window['WWOpenData'] && window['WWOpenData'].enableCanvasSharing && window['WWOpenData'].enableCanvasSharing()
63
+ }
64
+ if (loginUserInfo.UserAvatar.HasAvatar) {
65
+ getImageBase64ByUrl(loginUserInfo.Id).then((data) =>
66
+ drawAvatar(
67
+ {
68
+ name: loginUserInfo.Name,
69
+ userId: loginUserInfo.Id,
70
+ color: loginUserInfo.UserAvatar.Color,
71
+ },
72
+ 'data:image/jpeg;base64,' + data.obj,
73
+ ),
74
+ ).then(setAvatarSrc);
75
+ }else {
76
+ drawAvatar(
77
+ {
78
+ name: loginUserInfo.Name,
79
+ userId: loginUserInfo.Id,
80
+ color: loginUserInfo.UserAvatar.Color,
81
+ },
82
+ '',
83
+ ).then(setAvatarSrc);
84
+ }
85
+ drawName(loginUserInfo.Name,loginUserInfo.Id).then(setNameSrc)
86
+ return () => {
87
+ if (isWx()) {
88
+ window['WWOpenData'] && window['WWOpenData'].disableCanvasSharing && window['WWOpenData'].disableCanvasSharing()
89
+ }
90
+ }
91
+ }, []);
92
+
93
+ return (
94
+ <div className={preCls + '-content'} ref={cardRef}>
95
+ <img className={preCls + '__title'} src={require('./img/title.png')} />
96
+ <div className={preCls + '__date-range'}>6月7日-6月11日</div>
97
+ <div className={preCls + '__shadow'} />
98
+ <img className={preCls + '__laba'} src={require('./img/laba.png')}/>
99
+ <img className={preCls + '__bofang'} src={require('./img/bofang.png')}/>
100
+ <div className={preCls + '__body'}>
101
+ <div className={preCls + '__avatar'}>
102
+ <img src={avatarSrc} />
103
+ </div>
104
+ <img className={preCls + '__userName'} src={nameSrc}/>
105
+ <img className={preCls + '__quote'} src={require('./img/quote.png')} alt="" />
106
+ <div className={preCls + '__text'}>
107
+ 坚持每周反馈才是真正的优秀真正的优秀
108
+ </div>
109
+ <Board percent={80} />
110
+ <div className={preCls + '__comparison'}>
111
+ OKR 完成度
112
+ <img className={preCls + '__direction'} src={require('./img/up.png')} alt="" />
113
+ <span style={{color:'#4DC591'}}>20%</span>
114
+ </div>
115
+ <div className={preCls + '__colleague'}>
116
+ 恭喜超越了 <span>80%</span> 的同事
117
+ </div>
118
+ <Statistics/>
119
+ </div>
120
+ <img className={preCls + '__bottom'} src={require('./img/bottom.png')}/>
121
+ </div>
122
+ );
123
+ }
124
+
125
+ export default forwardRef(Card);
@@ -0,0 +1,81 @@
1
+ import openDataPainter from "./openDataPainter";
2
+ import setSize from "./setSize";
3
+ import { drawImage } from "./utils";
4
+
5
+ interface avatarParms {
6
+ url?: string;
7
+ color?: string;
8
+ name: string;
9
+ id: number;
10
+ width: number;
11
+ height: number;
12
+ x: number;
13
+ y: number;
14
+ maxNameWidth?: number;
15
+ }
16
+ export async function drawAvatar(shareData, avatar: string) {
17
+ if (window['WWOpenData'] && window['WWOpenData'].initCanvas) {
18
+ window['WWOpenData'].initCanvas()
19
+ }
20
+ const canvas = document.createElement('canvas');
21
+ let ctx = canvas.getContext('2d') as CanvasRenderingContext2D;
22
+ setSize(canvas, ctx, 72, 72);
23
+ ctx.beginPath();
24
+ await draw(ctx, {
25
+ width: 72,
26
+ height: 72,
27
+ x: 0,
28
+ y: 0,
29
+ url: avatar,
30
+ name: shareData.name,
31
+ id: shareData.userId,
32
+ color: shareData.color
33
+ });
34
+ const dataUrl = canvas.toDataURL();
35
+
36
+ return dataUrl;
37
+ }
38
+ async function draw (ctx: CanvasRenderingContext2D, params: avatarParms):Promise<number> {
39
+ ctx.save();
40
+ ctx.beginPath();
41
+ ctx.arc(
42
+ params.width / 2 + params.x,
43
+ params.height / 2 + params.y,
44
+ params.width / 2,
45
+ 0,
46
+ Math.PI * 2,
47
+ false,
48
+ );
49
+ ctx.clip();
50
+ ctx.closePath();
51
+ params.url ? await drawImageAvatar(ctx, params) : await drawTextAvatar(ctx, params);
52
+ ctx.restore();
53
+ return params.y + params.height;
54
+
55
+ }
56
+ function drawImageAvatar(ctx: CanvasRenderingContext2D, avatar: avatarParms) {
57
+ return drawImage(ctx,avatar.url as string,avatar.x,avatar.y,avatar.width,avatar.height)
58
+ }
59
+ function drawTextAvatar(ctx: CanvasRenderingContext2D, avatar: avatarParms) {
60
+ console.log('text')
61
+ const maxNameWidth = avatar.maxNameWidth || 28;
62
+ return new Promise<void>(async resolve => {
63
+ ctx.fillStyle = avatar.color as string;
64
+ ctx.fill();
65
+
66
+ ctx.closePath();
67
+ ctx.fillStyle = 'white';
68
+ ctx.font = '14px arial';
69
+ ctx.textBaseline = 'bottom';
70
+ let namePainter = await openDataPainter(ctx,{id:avatar.id,name:avatar.name,type:'userName'},22,maxNameWidth);
71
+ const { width, height } = namePainter;
72
+
73
+ namePainter.draw(
74
+ ctx,
75
+ avatar.x + avatar.width / 2 - width / 2,
76
+ avatar.y + avatar.height / 2 - height / 2,
77
+ );
78
+ ctx.closePath();
79
+ resolve();
80
+ });
81
+ }
@@ -0,0 +1,19 @@
1
+ import openDataPainter from "./openDataPainter";
2
+ import setSize from "./setSize";
3
+
4
+ export default async function(name,id){
5
+ const canvas = document.createElement('canvas');
6
+ let ctx = canvas.getContext('2d') as CanvasRenderingContext2D;
7
+ setSize(canvas, ctx, 295, 24);
8
+ ctx.beginPath();
9
+ const lineHeight = 24;
10
+ ctx.font = `bold 16px/${lineHeight}px arial,sans-serif`;
11
+ ctx.fillStyle = '#141C28';
12
+ ctx.textBaseline='middle';
13
+ const painter = await openDataPainter(ctx, {name,id,type:'userName'},24,295);
14
+ let x = (295 - (painter.width)) / 2
15
+ painter.draw(ctx,x,0)
16
+ const dataUrl = canvas.toDataURL();
17
+
18
+ return dataUrl;
19
+ }
@@ -0,0 +1,47 @@
1
+ import { getOpenId } from "&/components/common/openData";
2
+ import { isWx } from "&/components/helper";
3
+
4
+
5
+ interface openDataParam {
6
+ id: number; name: string; type: 'userName' | 'departmentName'
7
+ }
8
+
9
+ export default async function (
10
+ ctx: CanvasRenderingContext2D,
11
+ openDataParams: openDataParam,
12
+ lineHeight: number,
13
+ maxWidth: number = Infinity
14
+ ) {
15
+ let name = openDataParams.name
16
+ if (isWx()) {
17
+ name = await getOpenData(openDataParams)
18
+ }
19
+ const { width } = ctx.measureText(name);
20
+ let actualWidth = Math.min(width, maxWidth)
21
+ return {
22
+ width: actualWidth,
23
+ height: lineHeight,
24
+ draw: function (ctx: CanvasRenderingContext2D, x: number, y: number) {
25
+ ctx.save()
26
+ ctx.textBaseline = 'middle';
27
+ ctx.beginPath();
28
+ ctx.rect(x, y, actualWidth, lineHeight);
29
+ ctx.clip();
30
+ ctx.fillText(name, x, y + lineHeight / 2);
31
+ ctx.closePath()
32
+ ctx.restore()
33
+ }
34
+ }
35
+ }
36
+ const getOpenData = ({ id, name, type }: openDataParam) => {
37
+ const openId = getOpenId(id, type)
38
+ if (!window['WWOpenData'] || !openId) return Promise.resolve(name)
39
+ return new Promise<string>((resolve, reject) => {
40
+ window['WWOpenData'].prefetch({ items: [{ id: openId, type }] }, (err, data) => {
41
+ if (err) {
42
+ return reject(err)
43
+ }
44
+ resolve(data.items[0].data)
45
+ })
46
+ })
47
+ }
@@ -0,0 +1,12 @@
1
+ export default function (canvas: HTMLCanvasElement, ctx: CanvasRenderingContext2D, width, height) {
2
+ const devicePixelRatio = window.devicePixelRatio || 1;
3
+ const data = ctx.getImageData(0, 0, canvas.width, canvas.height);
4
+ //要将 canvas 的宽高设置成容器宽高的 2 倍
5
+ canvas.width = width * devicePixelRatio;
6
+ canvas.height = height * devicePixelRatio;
7
+ canvas.style.width = width + 'px';
8
+ canvas.style.height = height + 'px';
9
+ //然后将画布缩放,将图像放大两倍画到画布上
10
+ ctx.scale(devicePixelRatio, devicePixelRatio);
11
+ ctx.putImageData(data, 0, 0);
12
+ }
@@ -0,0 +1,83 @@
1
+ export function drawImage(
2
+ ctx: CanvasRenderingContext2D,
3
+ url: string,
4
+ x: number,
5
+ y: number,
6
+ width: number,
7
+ height: number,
8
+ ) {
9
+ return new Promise<void>(res => {
10
+ const img = new Image();
11
+ img.src = url;
12
+ img.onload = function () {
13
+ ctx.drawImage(img, x, y, width, height);
14
+ res();
15
+ };
16
+ });
17
+ }
18
+ export function drawTextMiddle(
19
+ ctx: CanvasRenderingContext2D,
20
+ text: string,
21
+ x: number,
22
+ y: number,
23
+ lineHeight: number,
24
+ maxWidth?: number,
25
+ textAlign?: 'left' | 'center'
26
+ ) {
27
+ ctx.textBaseline = 'middle';
28
+ if (!maxWidth) {
29
+
30
+ ctx.fillText(text, x, y + lineHeight / 2);
31
+ return y + lineHeight;
32
+ }
33
+ const lines = breakLinesForCanvas(ctx, text, maxWidth);
34
+ lines.forEach((l) => {
35
+ const { width } = ctx.measureText(l)
36
+ let left = x;
37
+ if (textAlign == 'center' && maxWidth) {
38
+ console.log(maxWidth, width)
39
+ left = (maxWidth - width) / 2 + x
40
+ }
41
+ ctx.fillText(l, left, y + lineHeight / 2);
42
+
43
+ y = y + lineHeight;
44
+ })
45
+ return y
46
+ }
47
+ function findBreakPoint(text, width, context) {
48
+ var min = 0;
49
+ var max = text.length - 1;
50
+
51
+ while (min <= max) {
52
+ var middle = Math.floor((min + max) / 2);
53
+ var middleWidth = context.measureText(text.substr(0, middle)).width;
54
+ var oneCharWiderThanMiddleWidth = context.measureText(text.substr(0, middle + 1)).width;
55
+ if (middleWidth <= width && oneCharWiderThanMiddleWidth > width) {
56
+ return middle;
57
+ }
58
+ if (middleWidth < width) {
59
+ min = middle + 1;
60
+ } else {
61
+ max = middle - 1;
62
+ }
63
+ }
64
+
65
+ return -1;
66
+ }
67
+
68
+ export function breakLinesForCanvas(ctx: CanvasRenderingContext2D, text: string, width: number) {
69
+ var result: string[] = [];
70
+ var breakPoint = 0;
71
+
72
+
73
+ while ((breakPoint = findBreakPoint(text, width, ctx)) !== -1) {
74
+ result.push(text.substr(0, breakPoint));
75
+ text = text.substr(breakPoint);
76
+ }
77
+
78
+ if (text) {
79
+ result.push(text);
80
+ }
81
+
82
+ return result;
83
+ }