YanTianFeng的知识库

Want Coding

Want Reading

文章 89

访问 18443

评论 2

头像

YanTianFeng

发私信

文章 89
访问 18443
评论 2
Technology and Code
返回顶部

Knowledge  图片水印

标签   水印  

  ( 14 )       ( 0 )


图片水印实现

水印模块

import { createGlobalStyle } from 'styled-components'

// 卡片水印
// 防止表格遮挡水印
const Water = createGlobalStyle`
  .ant-card {
    // prettier-ignore
    background-position: 0 0, 160PX 160PX !important;
    background-repeat: repeat, repeat !important;
    background-image: url('${window.location.origin}/script/account/print.svg'), url('${window.location.origin}/script/account/print.svg') !important;
  }
  .ant-table-placeholder {
    background: transparent !important;
  }
`

export default Water

获取水印

app / router.js

router.get('/script/account/print.svg', controller.script.account.print)

app / controller / script / account.js

'use strict'

const { Controller } = require('egg')
const path = require('path')
const TextToSVG = require('text-to-svg')

const textToSVG = TextToSVG.loadSync(path.resolve(__dirname, '../../fonts/SourceHanSansCN-Light.otf'))
const attributes = { fill: '#ededed', stroke: '#ededed', transform: 'rotate(-20, 90 75)' }
const options = { anchor: 'center middle', x: 160, y: 160, width: 320, height: 320, fontSize: 18, letterSpacing: 0.05, attributes }

const getSvgContent = text => {
  const svgPath = textToSVG.getPath(text, options)

  return `${svgPath}`
}

const loginRules = {
  token: {
    type: 'string',
    required: true,
  },
}

class EggController extends Controller {
  async print() {
    const accountInfo = await this.ctx.adminUser.getAccountInfo()
    const { isLogin, name, mobile } = accountInfo
    const content = isLogin ? `${name}${String(mobile).slice(7)}` : '小帮规划'

    this.ctx.type = 'image/svg+xml'
    this.ctx.body = getSvgContent(content)
  }

  async infojs() {
    const token = await this.ctx.cookieUtils.getToken()
    const accountInfo = await this.ctx.adminUser.getAccountInfo()
    const info = Object.assign({ token }, accountInfo)

    this.ctx.type = 'application/javascript'
    this.ctx.body = `
      window.APP_ACCOUNT = ${JSON.stringify(info)};
    `
  }

  async login() {
    try {
      this.ctx.validator.validateBody(loginRules)
    } catch (error) {
      return this.ctx.reject(10004, error.message)
    }

    const { token } = this.ctx.request.body
    this.ctx.cookieUtils.setToken(token)

    return this.ctx.resolve()
  }

  async logout() {
    const { deprecateTokenKey } = this.app.config

    this.ctx.cookieUtils.removeToken()
    this.ctx.cookies.set(deprecateTokenKey, null, this.ctx.cookieUtils.cookieOptions)

    return this.ctx.redirect('/')
  }
}

module.exports = EggController

依赖

package.json

"@types/styled-components": "^5.0.1",
"babel-plugin-styled-components": "^1.10.7",
"styled-components": "^5.0.1",

配置

.umirc.js

extraBabelPlugins: [
    [
      'babel-plugin-styled-components',
      {
        ssr: false,
        fileName: false,
        displayName: false,
      },
    ],
  ],

使用

import { useState, useEffect, Fragment } from 'react'
import { ConfigProvider } from 'antd'
import ProLayout from '@ant-design/pro-layout'
import Dashboard from '@xb/layouts/Dashboard'
import Water from '@xb/components/Water'
import PageLoading from '@xb/components/PageLoading'
import HeaderContent from '@xb/components/HeaderContent'
import router from 'umi/router'
import { registerApplication, start } from 'single-spa'
import { connect } from 'dva'
import iconLogo from '@xb/assets/logo.gif'

// 布局默认样式配置
const layoutSettings = {
  navTheme: 'dark',
  primaryColor: '#1890ff',
  layout: 'sidemenu',
  contentWidth: 'Fluid',
  fixedHeader: true,
  autoHideHeader: false,
  fixSiderbar: true,
  menu: {
    locale: true,
  },
  title: '小帮规划',
  pwa: false,
  colorWeak: false,
}

const { mobileLayoutPrefix, wxworkAuthBlackList, menuList, subappList } = window.APP_STATE

// 获取扁平菜单标识
const getFlattenKeys = menuList => {
  let flattenKeys = []

  menuList.forEach(item => {
    flattenKeys.push({
      path: item.path,
      keys: item.keys,
    })

    if (item.children) {
      flattenKeys = [...flattenKeys, ...getFlattenKeys(item.children)]
    }
  })

  return flattenKeys
}

// 判断当前菜单是否展开
const isMenuExpanded = (currentKeys = [], menuKeys = []) => {
  const currentKey = currentKeys.join(',')
  const menuKey = menuKeys.join(',')

  return currentKey.indexOf(menuKey) !== -1
}

// 获取父级菜单展开键
const getFatherKeys = (keys = []) => {
  return keys.filter((item, index) => index + 1 !== keys.length)
}

// 获取默认展开菜单
const flattenKeys = getFlattenKeys(menuList)
const defaultMenu = flattenKeys.find(item => item.path === window.location.pathname)
const defaultOpenKeys = defaultMenu ? defaultMenu.keys : []

const BasicLayout = ({ collapsed, location, dispatch }) => {
  const [openKeys, setOpenKeys] = useState(defaultOpenKeys)

  const { pathname } = location

  // 获取应用名称
  const getAppByPath = pathname => {
    const row = subappList.find(({ manifest }) => {
      return manifest.paths.some(prefix => pathname.startsWith(prefix))
    })

    return Object.assign({}, row)
  }

  // 应用注册
  useEffect(() => {
    subappList.forEach(({ name, manifest }) => {
      const loadingFunction = () => window.System.import(manifest.mainScript)

      const activityFunction = location => {
        const isMatched = manifest.paths.some(prefix => location.pathname.startsWith(prefix))
        return isMatched
      }

      registerApplication(name, loadingFunction, activityFunction)
      start()
    })
  }, [])

  // 侧边栏开关
  const onCollapse = collapsed => {
    dispatch({
      type: 'global/changeLayoutCollapsed',
      payload: Boolean(collapsed),
    })
  }

  // 获取当前子应用
  const { name: sourceAppName, manifest: sourceManifest } = getAppByPath(pathname)
  const hasMatched = Boolean(sourceAppName && sourceManifest)

  // 菜单数据
  const menuDataRender = () => menuList

  // 父级菜单
  const subMenuItemRender = (menuItemProps, defaultDom) => {
    const onMenuItemClick = () => {
      const isExpanded = isMenuExpanded(openKeys, menuItemProps.keys)
      const keys = isExpanded ? getFatherKeys(menuItemProps.keys) : menuItemProps.keys
      setOpenKeys(keys)
    }

    return (
      
{defaultDom}
) } // 基础菜单 // 参考文档 http://docs.xiaobangtouzi.com/pages/viewpage.action?pageId=6529045 const menuItemRender = (menuItemProps, defaultDom) => { const onItemClick = () => { setOpenKeys(menuItemProps.keys) const { name: targetAppName } = getAppByPath(menuItemProps.path) const httpReload = sourceAppName !== targetAppName const isReplacePath = pathname === menuItemProps.path switch (menuItemProps.type) { case 0: return window.open(window.APP_HERO.Linker.getDeprecatedAdminUrl(menuItemProps.path)) case 1: return window.open(window.APP_HERO.Linker.getInsuranceAdminUrl(menuItemProps.path)) case 2: if (httpReload) { return isReplacePath ? window.location.replace(menuItemProps.path) : window.open(menuItemProps.path, '_self') } return isReplacePath ? router.replace({ pathname: menuItemProps.path }) : router.push({ pathname: menuItemProps.path }) case 3: return window.open(menuItemProps.originalUrl) default: return null } } return (
{defaultDom}
) } const children = (
{/* 首页友情提示 */} {pathname === '/' && } {/* 子应用匹配成功显示默认加载动画 */} {hasMatched && }
{/* 异步加载样式 */} {hasMatched && }
) // 没有侧边栏 const withoutLayout = wxworkAuthBlackList.includes(pathname) || pathname.startsWith(mobileLayoutPrefix) if (withoutLayout) { return {children} } return ( } {...layoutSettings} > {children} ) } const connector = ({ global: { collapsed } }) => ({ collapsed }) export default connect(connector)(BasicLayout)