From 7b67c55271d11570253b0a363e2e865ae7548b70 Mon Sep 17 00:00:00 2001 From: hisoka0728 <1399952343@qq.com> Date: Mon, 19 Aug 2024 17:52:27 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=8F=90=E4=BA=A4=E6=A0=87=E7=AD=BE?= =?UTF-8?q?=E5=A2=99=E6=8F=92=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/index.ts | 2 + src/tagged-wall/index.ts | 13 ++++ src/tagged-wall/provider.ts | 13 ++++ src/tagged-wall/tag.tsx | 41 +++++++++++ src/tagged-wall/tagged-wall.scss | 24 +++++++ src/tagged-wall/tagged-wall.tsx | 97 ++++++++++++++++++++++++++ src/tagged-wall/tags.scss | 6 ++ src/tagged-wall/utils.ts | 113 +++++++++++++++++++++++++++++++ 8 files changed, 309 insertions(+) create mode 100644 src/tagged-wall/index.ts create mode 100644 src/tagged-wall/provider.ts create mode 100644 src/tagged-wall/tag.tsx create mode 100644 src/tagged-wall/tagged-wall.scss create mode 100644 src/tagged-wall/tagged-wall.tsx create mode 100644 src/tagged-wall/tags.scss create mode 100644 src/tagged-wall/utils.ts diff --git a/src/index.ts b/src/index.ts index 83b5aa2..a567cde 100644 --- a/src/index.ts +++ b/src/index.ts @@ -12,6 +12,7 @@ import { IBizPercentPond } from './percent-pond'; import { IBizCustomButton } from './custom-button'; import { IBizWaterLevelPond } from './water-level-pond'; import { IBizCustomImageSearchBox } from './custom-image-search-box'; +import { IBizTaggedWall } from './tagged-wall'; // 自定义边框 import { @@ -56,6 +57,7 @@ export default { _app.use(IBizCustomButton); _app.use(IBizWaterLevelPond); _app.use(IBizCustomImageSearchBox); + _app.use(IBizTaggedWall); // 自定义边框 _app.use(IBizCustomDV1); diff --git a/src/tagged-wall/index.ts b/src/tagged-wall/index.ts new file mode 100644 index 0000000..9571e51 --- /dev/null +++ b/src/tagged-wall/index.ts @@ -0,0 +1,13 @@ +import { App } from 'vue'; +import { withInstall } from '@ibiz-template/vue3-util'; +import { registerControlProvider } from '@ibiz-template/runtime'; +import { TaggedWall } from './tagged-wall'; +import { TaggedWallProvider } from './provider'; + +export const IBizTaggedWall = withInstall(TaggedWall, function (v: App) { + v.component(TaggedWall.name, TaggedWall); + registerControlProvider( + 'LIST_RENDER_TAGGED_WALL', + () => new TaggedWallProvider(), + ); +}); diff --git a/src/tagged-wall/provider.ts b/src/tagged-wall/provider.ts new file mode 100644 index 0000000..30ad829 --- /dev/null +++ b/src/tagged-wall/provider.ts @@ -0,0 +1,13 @@ +import { IControlProvider } from '@ibiz-template/runtime'; +/** + * 列表适配器 + * + * @author lxm + * @date 2022-10-25 18:10:57 + * @export + * @class ListProvider + * @implements {IControlProvider} + */ +export class TaggedWallProvider implements IControlProvider { + component: string = 'TaggedWall'; +} diff --git a/src/tagged-wall/tag.tsx b/src/tagged-wall/tag.tsx new file mode 100644 index 0000000..0434b10 --- /dev/null +++ b/src/tagged-wall/tag.tsx @@ -0,0 +1,41 @@ +import { computed, defineComponent } from 'vue'; +import { useNamespace } from '@ibiz-template/vue3-util'; +import { $RandomColor, $Normal } from './utils'; +import './tags.scss'; + +export const CustomTag = defineComponent({ + name: 'CustomTag', + props: { + tname: { + type: String, + required: true, + }, + bgcolor: { + type: String, + }, + color: { + type: String, + }, + }, + setup() { + const ns = useNamespace('custom-tag'); + const setColor = computed(() => $RandomColor()); + const normalSize = computed(() => `${$Normal(16, 8)}px`); + + return { + ns, + setColor, + normalSize, + }; + }, + render() { + return ( + + {this.tname} + + ); + }, +}); diff --git a/src/tagged-wall/tagged-wall.scss b/src/tagged-wall/tagged-wall.scss new file mode 100644 index 0000000..5f2ec47 --- /dev/null +++ b/src/tagged-wall/tagged-wall.scss @@ -0,0 +1,24 @@ +@include b(tagged-wall) { + @include e(content) { + margin: 0 auto; + text-align: center; + } + + @include e(tag-body) { + display: inline-block; + width: 100%; + margin: auto; + } + + @include e(tag-body-tags){ + text-align: center; + word-break: break-word; + + } + + @include e(tag-body-tags-li){ + min-height: 30px; + text-align: center; + } + +} diff --git a/src/tagged-wall/tagged-wall.tsx b/src/tagged-wall/tagged-wall.tsx new file mode 100644 index 0000000..1e40cd2 --- /dev/null +++ b/src/tagged-wall/tagged-wall.tsx @@ -0,0 +1,97 @@ +/* eslint-disable array-callback-return */ +import { useControlController, useNamespace } from '@ibiz-template/vue3-util'; +import { computed, defineComponent, PropType, ref, watch } from 'vue'; +import { IDEList } from '@ibiz/model-core'; +import { IControlProvider, ListController } from '@ibiz-template/runtime'; +import './tagged-wall.scss'; +import { $NormalSort, $RandomSplit } from './utils'; +import { CustomTag } from './tag'; + +export const TaggedWall = defineComponent({ + name: 'TaggedWall', + component: [CustomTag], + props: { + modelData: { type: Object as PropType, required: true }, + context: { type: Object as PropType, required: true }, + params: { type: Object as PropType, default: () => ({}) }, + provider: { type: Object as PropType }, + /** + * 部件行数据默认激活模式 + * - 0 不激活 + * - 1 单击激活 + * - 2 双击激活(默认值) + * + * @type {(number | 0 | 1 | 2)} + */ + mdctrlActiveMode: { type: Number, default: undefined }, + + /** + * 是否为单选 + * - true 单选 + * - false 多选 + * + * @type {(Boolean)} + */ + singleSelect: { type: Boolean, default: undefined }, + isSimple: { type: Boolean, required: false }, + loadDefault: { type: Boolean, default: true }, + }, + setup() { + const c = useControlController((...args) => new ListController(...args)); + const ns = useNamespace(`tagged-wall`); + const list = ref([]); + const tagList = ref([]); + const tags = computed(() => { + // eslint-disable-next-line vue/no-side-effects-in-computed-properties + const arr = $RandomSplit(tagList.value.length, 7); + // eslint-disable-next-line vue/no-side-effects-in-computed-properties + list.value = $NormalSort(arr); // 获取数据结构 + // eslint-disable-next-line vue/no-side-effects-in-computed-properties + const temp = tagList.value + .sort(() => { + // 重新随机排序 + return Math.random() > 0.5 ? -1 : 1; + }) + .concat(); + return list.value.map((v, _k) => { + // 根据list生成数据结构 + return temp.splice(0, v); + }); + }); + + watch( + () => c.state.items, + () => { + tagList.value = c.state.items; + }, + ); + + return { + c, + ns, + tags, + tagList, + }; + }, + render() { + return ( +
+
+
+ {this.tags.map((item, index) => { + return ( +
+ {item.map(tag => { + return ( + + ); + })} +
+ ); + })} +
+
+
+ ); + }, +}); diff --git a/src/tagged-wall/tags.scss b/src/tagged-wall/tags.scss new file mode 100644 index 0000000..ed4887d --- /dev/null +++ b/src/tagged-wall/tags.scss @@ -0,0 +1,6 @@ +@include b(custom-tag){ + display: inline-block; + margin:5px; + font-size: 24px; + user-select: none; +} \ No newline at end of file diff --git a/src/tagged-wall/utils.ts b/src/tagged-wall/utils.ts new file mode 100644 index 0000000..c31f485 --- /dev/null +++ b/src/tagged-wall/utils.ts @@ -0,0 +1,113 @@ +/* eslint-disable prefer-spread */ +function $RandomSplit(total: number, nums: number): number[] { + let rest = total; + const result = Array.from({ length: nums }, (n, i) => nums - i).map(n => { + const v = 1 + Math.floor(Math.random() * ((rest / n) * 2 - 1)); + rest -= v; + return v; + }); + result[nums - 1] += rest; + return result; +} + +function $NormalSort(arr: number[]): number[] { + const temp: number[] = []; + let i = 0; + const l = arr.length; + const leftTo = 0; + const rightTo = 0; + + // Sort the array in descending order + const sortArr = arr.sort((a, b) => b - a); + + while (sortArr.length > 1) { + const a = sortArr.pop()!; + const b = sortArr.pop()!; + + // Determine where to place the elements based on the current state of `leftTo` and `rightTo` + if (leftTo < rightTo) { + temp[i] = b; + temp[l - (i + 1)] = a; + } else { + temp[i] = b; + temp[l - (i + 1)] = a; + } + + // eslint-disable-next-line no-plusplus + i++; + } + + // If there is an odd number of elements, add the last element to the end of the `temp` array + if (sortArr.length === 1) { + temp[i] = sortArr.pop()!; + } + + return temp; +} + +function $Normal(mean: number, sigma: number): number { + let u = 0.0; + let v = 0.0; + let w = 0.0; + let c = 0.0; + do { + // Obtain two independent random variables in the range (-1, 1) + u = Math.random() * 2 - 1.0; + v = Math.random() * 2 - 1.0; + w = u * u + v * v; + } while (w === 0.0 || w >= 1.0); + c = Math.sqrt((-2 * Math.log(w)) / w); + return mean + u * c * sigma; +} + +// 首字母配置颜色 +const colorArr = { + a: 'rgb(17, 1, 65)', + b: 'rgb(113, 1, 98)', + c: 'rgb(161, 42, 94)', + d: 'rgb(237, 3, 69)', + e: 'rgb(239, 106, 50)', + f: 'rgb(251, 191, 69)', + g: 'rgb(170, 217, 98)', + h: 'rgb(3, 195, 131)', + i: 'rgb(1, 115, 81)', + j: 'rgb(1, 84, 90)', + k: 'rgb(38, 41, 74)', + l: 'rgb(26, 19, 52)', + m: 'rgb(0, 102, 119)', + n: 'rgb(119, 153, 85)', + o: 'rgb(255, 170, 102)', + p: 'rgb(255, 119, 119)', + q: 'rgb(199, 96, 101)', + r: 'rgb(23, 103, 87)', + s: 'rgb(188, 173, 148)', + t: 'rgb(83, 109, 114)', + u: 'rgb(102, 188, 41)', + v: 'rgb(181, 231, 146)', + w: 'rgb(232, 247, 221)', + x: 'rgb(113, 39, 122)', + y: 'rgb(213, 150, 221)', + z: 'rgb(242, 224, 245)', +}; +// 随机颜色 +const $RandomColor = function () { + const r = Math.floor(Math.random() * 256); + const g = Math.floor(Math.random() * 256); + const b = Math.floor(Math.random() * 256); + return `rgb(${r},${g},${b})`; +}; + +const $RandomColor2 = function () { + return `hsl(${Math.round(Math.random() * 360)},${Math.round( + Math.random() * 100, + )}%,${Math.round(Math.random() * 80)}%)`; +}; + +export { + $RandomSplit, + $NormalSort, + $Normal, + colorArr, + $RandomColor, + $RandomColor2, +}; -- Gitee