import { IconStrikethrough, IconTextBold, IconTextCenter, IconTextItalic, IconTextJustify, IconTextLeft, IconTextLetterSpacing, IconTextLineHeight, IconTextRight, IconTextSize, IconTextUnderline, } from "@/assets/icons"; import { css } from "@linaria/core"; import { Button, InputNumber, Tooltip } from "ant-design-vue"; import { useEditor } from "@/modules/editor"; import Select from "@queenjs-modules/queditor/components/FormUI/Items/Select"; import "@simonwep/pickr/dist/themes/nano.min.css"; import _ from "lodash"; import { queenApi } from "queenjs"; import { defineComponent, onMounted, onUnmounted, reactive, ref, toRaw, watch, } from "vue"; import { any, bool, func, number, object, string } from "vue-types"; interface ColumnItem { label?: string; component?: ((...args: any[]) => any) | Record; dataIndex?: string; props?: { [name: string]: any }; itemProps?: { [name: string]: any }; changeExtra?: (data: any) => any; } export const TextColor = defineComponent({ props: { value: string().def("#666666"), }, emits: ["change"], setup(props, { emit }) { let pickerRef = ref(); const state = reactive({ color: props.value, }); watch( () => props.value, () => { state.color = props.value; } ); const colorChange = (e: any) => { const hexa = e.target.value; emit("change", hexa); state.color = hexa; }; return () => (
{ pickerRef?.value.click(); }} >
); }, }); export const AlignComp = defineComponent({ props: { value: string<"left" | "right" | "center" | "justify">().def("left"), }, emits: ["change"], setup(props, { emit }) { const aligns = [ { label: "左对齐", key: "left", icon: , }, { label: "居中对齐", key: "center", icon: , }, { label: "右对齐", key: "right", icon: , }, { label: "两端对齐", key: "justify", icon: , }, ]; return () => (
{aligns.map((e: any) => { return ( ); })}
); }, }); export const LetterSpacingComp = defineComponent({ props: { value: any().def(0), }, emits: ["change"], setup(props, { emit }) { return () => { const value = typeof props.value === "string" ? parseInt(props.value) : props.value; return ( } defaultValue={0} min={0} max={100} step={1} value={value} onChange={(value: any) => { if (!value) { emit("change", "0px"); return; } emit("change", value + "px"); }} /> ); }; }, }); export const LineHeightComp = defineComponent({ props: { value: any().def(1.5), }, emits: ["change"], setup(props, { emit }) { return () => { const value = typeof props.value === "string" ? parseFloat(props.value) : props.value; return ( } defaultValue={1.5} min={0.5} max={3} step={0.5} value={value || 1.5} onChange={(value: any) => { if (!value) { emit("change", 1.5); return; } emit("change", value); }} /> ); }; }, }); export const FontStyleWapper = defineComponent({ emits: ["change"], setup(props, { emit }) { const fontStyleColumns = [ { label: "加粗", dataIndex: "bold", icon: , }, { label: "斜体", dataIndex: "italic", icon: , }, { label: "下划线", dataIndex: "underline", icon: , }, { label: "删除线", dataIndex: "strikethrough", icon: , }, ]; const changeVal = (e: any) => { emit("change", e); }; return () => (
{fontStyleColumns.map((e: any) => { return ( { return ; }, }} onChange={changeVal} /> ); })}
); }, }); export const FontStyleComp = defineComponent({ props: { icon: any(), value: bool().def(false), }, emits: ["change"], setup(props, { emit }) { return () => { return ( ); }; }, }); export const FontFamily = defineComponent({ props: { value: string().def(""), }, emits: ["change"], setup(props, { emit }) { const options = [ { label: "默认字体", value: "" }, { label: "宋体", value: "宋体,Songti,STSong,serif" }, { label: "黑体", value: "黑体,Heiti,STHeiti,sans-serif" }, { label: "仿宋", value: "仿宋,FangSong,STFangsong,serif" }, { label: "楷体", value: "楷体,KaiTi,STKaiti,sans-serif" }, ]; return () => { return ( ); }; }, }); export const FontSize = defineComponent({ props: { value: any().def("12px"), }, emits: ["change"], setup(props, { emit }) { return () => { return ( } defaultValue={12} min={12} max={60} value={parseInt(props.value) || 12} onChange={(value: any) => { if (!value) { emit("change", "12px"); return; } emit("change", value + "px"); }} /> ); }; }, }); export const LinkButton = defineComponent({ props: { icon: any(), value: any(), }, emits: ["change"], setup(props, { emit }) { const showLinkInput = async () => { const res = await queenApi.showInput({ title: "请输入链接地址", defaultValue: "http://", }); emit("change", res); }; return () => ( ); }, }); export const TextToolItem = defineComponent({ props: { column: object(), index: number(), onChange: func(), }, setup(props) { const state = reactive({ value: undefined, }); const { controls } = useEditor(); let editor: any = null; watch( () => controls.textEditorCtrl.state.currEditor, () => { editor = toRaw(controls.textEditorCtrl.state.currEditor); initCommands(); } ); function handleValueChange() { const { column } = props; if (!editor) { return; } const command = editor.commands.get(column?.dataIndex); if (command) { state.value = command.value; } } const initCommands = () => { const { column } = props; if (!editor) { return; } const command = editor.commands.get(column?.dataIndex); if (command) { console.log("init", column?.dataIndex, command.value); state.value = command.value; command.on("change:value", handleValueChange); } }; onMounted(() => { initCommands(); }); onUnmounted(() => { const { column } = props; if (!editor) { return; } const command = editor.commands.get(column?.dataIndex); if (command) { command.off("change:value", handleValueChange); } }); const changeVal = (value: any, ...args: any[]) => { const { column } = props; let params = { dataIndex: column?.dataIndex, value: { value }, ...args, }; if (column?.changeExtra) params = column.changeExtra?.(params); props.onChange?.(params); return params; }; const component = props.column?.component || null; return () => { const { column, index } = props; return (
e.stopPropagation()} > {column?.label ? ( ) : ( )}
); }; }, }); const currStyle = css` color: @inf-primary-color; &:hover, &:focus { color: @inf-primary-color; } `; const ColorPicker = css` position: relative; width: 32px; height: 32px; border-radius: 2px; cursor: pointer; .color_picker { width: 100%; height: 100%; border-radius: 2px; border: 1px solid transparent; &:focus, &:hover { border-color: @inf-primary-color; box-shadow: 0 0 0 2px rgba(232, 139, 0, 0.2); } } .color_input { position: absolute; left: 0; bottom: 0; width: 100%; height: 0; padding: 0; border: none; visibility: hidden; } `; const AlignCompWapper = css` display: flex; .ant-btn { flex: 1; width: 100%; line-height: 1; .inficon { font-size: 22px; } } `; const FontStyleCompWapper = css` flex: 1; display: flex; align-items: center; margin-right: 12px; border-radius: 2px; & > div { flex: 1; border-radius: 0; .ant-btn { width: 100%; line-height: 1; .inficon { font-size: 22px; } } } `; const formItemStyles = css` height: 100%; flex: 1; margin-right: 12px; background-color: #303030; border-radius: 2px; &:last-child { margin-right: 0; } &.disabled { cursor: not-allowed; } `;