feng 发布的文章

记录一下自动化部署ssr过程

记录一下,免的自己后面忘记.

下载脚本&运行脚本

wget --no-check-certificate -O shadowsocks.sh https://raw.githubusercontent.com/teddysun/shadowsocks_install/master/shadowsocks.sh
chmod +x shadowsocks.sh
./shadowsocks.sh 2>&1 | tee shadowsocks.log

另外一个源

wget --no-check-certificate https://raw.githubusercontent.com/quniu/shadowsocks-all/master/install/shadowsocks-all.sh
chmod +x shadowsocks-all.sh
./shadowsocks-all.sh 2>&1 | tee shadowsocksR.log

安装

第一步输入密码,
第二步输入端口号,
第三步输入加密方式 (默认7)

任意键等待安装

修改配置文件

vi /etc/shadowsocks.json 

配置防火墙

systemctl stop firewalld.service

启动/停止ss服务

ssserver -c /etc/shadowsocks.json -d start
ssserver -c /etc/shadowsocks.json -d stop
// 端口处理
// 查看所有打开的端口: 
firewall-cmd --zone=public --list-ports
// 添加
firewall-cmd --zone=public --add-port=80/tcp --permanent    (--permanent永久生效,没有此参数重启后失效)
// 重新载入
firewall-cmd --reload
// 查看
firewall-cmd --zone= public --query-port=80/tcp
// 删除
firewall-cmd --zone= public --remove-port=80/tcp --permanent

开启bbr加速

wget --no-check-certificate https://github.com/teddysun/across/raw/master/bbr.sh
chmod +x bbr.sh
./bbr.sh

重启后验证是否开启bbrlsmod | grep bbr返回看到 tcp_bbr 就说明 BBR 已经启动了

记录一下v2ray

bash <(curl -L -s https://install.direct/go.sh)

注意要处理防火墙

C#通过Jurassic实现运行js脚本代码

做网络爬虫抓取页面数据的时候经常会有下面的情况:
很多网站的前端代码里面,会对某些数值或者字符串做加密解密处理后生成令牌,从而达到让其他人无法轻易调用自己对外开放的接口.
这个时候就希望后台能直接执行js代码,省得还要自己写一遍.
本人主要用C#来写,写一下c#执行js脚本代码的步骤.
c#执行js脚本的库有很多,推荐用jurassic,简单通用,限制少.
首先jurassic的dll文件推荐直接用nuget安装,比较省心省事.

关键代码如下:

...
using Jurassic;

...
string jsFun = @"
    ....
    function aaa(a,b){
        return a + b;
    }
    ....
";    // js 脚本 脚本里面可以复制很多个js的function
ScriptEngine sc = new ScriptEngine();
sc.Execute(jsFun);    // 执行js脚本 
double z = sc.Evaluate<double>("aaa(5,6);"); // 注意如果是字符串变量的话,变量左右要加 '
这样就能运行js脚本的函数得到最终值了.

sc.Evaluate还能执行js表达式,不过上面的用法用的最多,其他的就不多说了

WEBGL 编程指南 unexpected token after conditional expression

WEBGL编程指南书中对应的demo文件中,有好几个demo文件直接运行无法显示页面效果,控制台会报错:

Failed to compile shader: ERROR: 0:3: 'GL_ES' : unexpected token after conditional expression

原因是demo中写错了,修改一下即可:

...
// Fragment shader program
var FSHADER_SOURCE =
  '#ifdef GL_ES\n' +
  'precision mediump float;\n' + // Precision qualifier (See Chapter 6)
  '#endif GL_ES\n' +
...

这里#endif 不应该加GL_ES,去掉即可,那一行改成:
'#endif \n' +

笔者应该是复制错了吧...我看了一下好多地方是这样写.
为像我一下在学这本书的人记录一下.

ajax请求后无法打开新页面

最近项目需求需要在系统中打开其他系统的内部网页,一开始是ajax请求本地后台,后台解析得到token后返回,然后前端跳转,发现这样做浏览器不会执行window.open打开新页面.
解决方案:1 同步ajax,2 先新建窗口,然后ajax后对新窗口的location.href赋值
其实第2种方案有特定情况下没法访问的问题.

个人认为最佳方案还是不通过ajax请求,直接打开新窗口,让后台重定向比较好,最终解决方案也是这样去做的

在Vue框架中制作弹出窗

因为公司项目需要,在页面表格中很多地方的数字需要制作弹出窗口,由于弹出层非常多,弹出层中还需要展示弹出层,并且希望弹出层互相不影响.虽然有不少弹出层开源框架,但是都不支持动态创建弹出层(不在template模板中写),并且能够通过插槽的方式插入其他组件.主要原因是vue中想要使用组件,必须在components中有定义过或者组件是全局组件,这就导致了不好开发类似jquery形式的创建弹出层中传入插槽组件.
考虑到弹出层过多,如果在模板里定义弹出层过于繁琐,针对自己项目写了个弹出层组件.

首先是弹出层样式(这个基本差不多,按照各自项目的样式来写

<template>
  <transition enter-active-class="dialog-showIn" leave-active-class="dialog-showOut" @after-enter="afterEnter" @after-leave="afterLeave">

    <div v-show="visible" ref="popup" class="popup popup-bground animated" :style="popupStyle()">
      <div ref="title" class="title" :style="{cursor:cursor}">
        <div class="name" :style="titleStyle">{{ title || '标题' }}</div>
        <div @click.stop="close()" class="close">
          <i class="iconfont icon-guanbi2"></i>
        </div>
      </div>
      <div ref="main" class="main" :class="mainClassName">
        <slot></slot>
      </div>
    </div>
  </transition>
</template>
<script>
import initDrag from '@/assets/js/drag'
export default {
  name: 'GridDialog',
  props: {
    show: Boolean,
    mainClassName: {
      type: String,
      default: ''
    },
    title: {
      default: '',
      type: String
    },
    titleStyle: {
      default: ''
    },
    top: {
      default: '',
      type: String
    },
    left: {
      default: '',
      type: String
    },
    right: {
      default: '',
      type: String
    },
    bottom: {
      default: '',
      type: String
    },
    width: {
      type: String,
      default: '4rem'
    },
    height: {
      type: String,
      default: '3rem'
    },
    fullPage: {
      type: Boolean,
      default: false
    },
    fullWindow: {
      type: Boolean,
      default: false
    },
    zIndex: {
      type: Number,
      default: 101
    }
  },
  data() {
    return {
      y: '',
      x: '',
      r: '',
      b: '',
      visible: false
    }
  },
  computed: {
    cursor() {
      return this.fullPage || this.fullWindow ? 'default' : 'move'
    },
    popupWidth() {
      return this.fullWindow ? '90%' : this.width
    },
    popupHeight() {
      return this.fullWindow ? '90%' : this.height
    }
  },
  created() {
    // console.log('right:' + this.right)
    if (this.fullPage) {
      this.y = '0px'
      this.x = '0px'
    } else if (this.fullWindow) {
      this.x = '5%'
      this.y = '5%'
    } else {
      this.y = this.top
      this.x = this.left
      this.r = this.right
      this.b = this.bottom
    }
    this.visible = this.show
  },
  mounted() {
    if (this.b) {
      this.$refs.popup.style.bottom = this.b
    } else if (this.y) {
      this.$refs.popup.style.top = this.y
    } else {
      let height = $(window).height()
      this.$refs.popup.style.top =
        (height - $(this.$refs.popup).height()) / 2 + 'px'
    }

    if (this.r) {
      this.$refs.popup.style.right = this.r
    } else if (this.x) {
      this.$refs.popup.style.left = this.x
    } else {
      let width = $(window).width()
      this.$refs.popup.style.left =
        (width - $(this.$refs.popup).width()) / 2 + 'px'
    }

    this.$nextTick(() => {
      if (!this.fullPage && !this.fullWindow) {
        initDrag(this.$refs.title, this.$refs.popup, data => {
          // this.y = data.y + 'px';
          // this.x = data.x + 'px';
        })
      }
    })
  },
  methods: {
    close() {
      this.$emit('close', false)
    },
    afterLeave() {
      this.$emit('closed')
    },
    afterEnter() {
      this.$emit('opened')
    },
    popupStyle() {
      if (this.fullPage) {
        return {
          width: '100vw',
          height: '100vh',
          'z-index': this.zIndex
        }
      } else {
        return {
          width: this.popupWidth,
          height: this.popupHeight,
          'z-index': this.zIndex
        }
      }
    }
  },
  watch: {
    show(val) {
      this.visible = val
    }
  }
}
</script>

上面的弹出层就是普通的弹出层,可以在其他的template模板中引用显示,下面是为jquery形式js代码弹出所写:

import GridDialog from './GridDialog.vue'
import components from './components'
const props = GridDialog.props

export default {
  components: components, // 这段是单独一个js引入所有需要加载插槽的组件,如果没有定义,外部弹出会报错
  props: {
    ...props,
    slotName: {
      type: String,
      default: null
    },
    slotProps: {
      type: Object,
      default: null
    },
    id: {
      type: String,
      default: null
    }
  },
  data() {
    return {
      visible: false,
      isOpened: false
    }
  },
  render(h) {
    var child = null
    if (this.slotName != null) {
      child = h(this.slotName, {
        props: { ...this.slotProps, isVisible: this.isOpened }
      })
    }

    return (
      <GridDialog
        title={this.title}
        show={this.visible}
        mainClassName={this.mainClassName}
        titleStyle={this.titleStyle}
        top={this.top}
        left={this.left}
        right={this.right}
        bottom={this.bottom}
        width={this.width}
        height={this.height}
        fullWindow={this.fullWindow}
        fullPage={this.fullPage}
        zIndex={this.zIndex}
        on-close={() => this.close()}
        on-closed={() => this.closed()}
        on-opened={() => this.opened()}
      >
        {child}
      </GridDialog>
    )
  },
  methods: {
    close() {
      this.visible = false
      this.isOpened = false
    },
    closed() {
      this.$emit('closed')
    },
    opened() {
      this.isOpened = true
    }
  }
}

然后专门写一个弹出层池,用来管理弹出框

import Vue from 'vue'
import Component from './fun-griddialog.jsx'
import router from '@/router'
import store from '@/store/index'

const Constructor = Vue.extend(Component)

let instances = []
let numbers = 0
let zindexNumbers = 9999999
const removeInstance = instance => {
  const index = instances.findIndex(t => instance.id == t.id)
  if (index != -1) {
    instances.splice(index, 1)
  }
}

const getInstanceById = id => {
  const instance = instances.find(t => t.id == id);
  return instance;
}

const popup = options => {
  const props = options.props || {};
  const slotName = options.slotName || null;
  const slotProps = options.slotProps || {};
  // 这里需要把router和store传入,否则的话自定义插槽如果用到了store,这个组件是不在总App组件下,无法使用store的
  const instance = new Constructor({
    router,
    store,
    propsData: {
      ...props,
      slotName,
      slotProps,
      zIndex: ++zindexNumbers,
      show: false
    }
  })

  if (options.id) {
    let ins = getInstanceById(options.id);
    if (ins) {
      ins.vm.visible = true;
      return;
    }
  }

  instance.id = options.id || `__popup_dialog__${++numbers}`
  if (options.id) {
    instance.__cache = true;
  }
  instance.vm = instance.$mount()
  document.body.appendChild(instance.vm.$el)
  instance.vm.visible = true

  instances.push(instance)

  instance.vm.$on('close', () => {
    instance.vm.visible = false
  })
  // 有些弹出层希望能缓存起来,不要点关闭后关闭,约定在外部传入id则不销毁.
  instance.vm.$on('closed', () => {
    if (!instance.__cache) {
      removeInstance(instance)
      document.body.removeChild(instance.vm.$el)
    }
  })
// 对弹出层添加鼠标按下事件,改变他的zIndex,从而让弹出层放到最上层
  instance.vm.$el.addEventListener('mousedown', e => {
    // console.log('mousedown')
    instance.vm.zIndex = ++zindexNumbers;
  })

  return instance.vm
}

export default popup

这样就基本上写好了针对我们项目的弹出层,但是这种弹出层确实很难做到通用(2个问题: 1:Vue组件必须在components中定义才能使用,如果都是全局注册也不太好. 2: 这类组件基本上不在App(根组件)的下面,如果想在根组件下面,仍然会有很多耦合代码,所以基本也要用硬编码去引入类似vuex和vue-router组件)基于上面两点,实在想不到怎么做通用框架,本身的vue组件库确实也没有看到能有这样的的弹出层功能,(只能是基本功能,不能引用自定义组件)
最后使用就很简单,

import GridDialog from './GridDialog.vue'
import popup from './function'
export default (Vue) => {
  Vue.component(GridDialog.name, GridDialog)
  Vue.prototype.$popup = popup;
}
// 在main入口里面写入
// import xxx from './...js'
// Vue.use(xxx)

// 在需要弹出的地方直接写:
      this.$popup({
        props: {
          title:'标题',
          // fullPage: true
          //width: '1000px',
          //height: '500px'
          fullWindow: true
        },
        slotName: 'UnitContainer',   //组件名称(必须在上面的component中引用)
        slotProps: {                //组件需要传入的参数
          areaId: item.areaId,
          deviceType: this.activeDeviceType.value
        }
      })

记录一下,下次需要用到时有地方可以查阅