Joyber 发布的文章

GITHUB地址

<?php

// 字符串转BcMath计算结果
class StrToBcmath {
    /**
     * @var int
     */
    private $scale; // 精度

    /**
     * @var mixed   // 是否输出计算过程
     */
    private $isecho;

    /**
     * @param $scale    // 可选,精度,默认值:8
     * @param $isecho   // 可选,是否输出计算过程,默认值:false
     */
    public function __construct($scale = 8, $isecho = false) {
        $this->scale  = $scale;
        $this->isecho = $isecho;
    }

    // 主方法
    /**
     * @param $expression   // 复杂运算表达式
     * @param $scale    // 精度
     * @param $isRecursive  // 是否递归,递归时不输出计算过程
     */
    public function of($expression, $scale = '', $isRecursive = false) {
        $scale = $scale ?: $this->scale;

        // 原始表达式
        if (!$isRecursive && $this->isecho) {
            echo $expression . "\n";
        }

        // 去除空格
        if (!$isRecursive) {
            $expression = str_replace(' ', '', $expression);
        }

        //避免$expression=0,出现InvalidArgumentException错误
        if (is_numeric($expression) && $expression == 0) return 0;

        // 如果输入的表达式为空或者包含非法字符,则抛出异常
        if (empty($expression) || preg_match('/[^0-9\.\+\-\*\/\(\)]/', $expression)) {
            throw new \InvalidArgumentException('表达式错误,仅支持+,-,*,/,**,(),数字:' . $expression);
        }

        // 使用正则表达式匹配表达式中的括号
        while (preg_match('/\(([^\(\)]+)\)/', $expression, $matches)) {
            // 计算括号中的表达式
            $res = $this->of($matches[1], $scale, true);
            // 将没有括号的表达式替换到原表达式中
            $expression = str_replace('(' . $matches[1] . ')', $res, $expression);
            if ($this->isecho) {
                echo '=' . $expression . "\n";
            }
        }

        // 处理指数运算
        while (preg_match('/(\d+(\.\d+)?)(\*\*)(\d+(\.\d+)?)/', $expression, $matches)) {
            $res        = $this->basic($matches[0], $scale);
            $expression = str_replace($matches[0], $res, $expression);
            if (!$isRecursive && $this->isecho) {
                echo '=' . $expression . "\n";
            }
        }

        // 处理乘法、除法
        while (preg_match('/(\d+(\.\d+)?)([\/*])(\d+(\.\d+)?)/', $expression, $matches)) {
            $res        = $this->basic($matches[0], $scale);
            $expression = str_replace($matches[0], $res, $expression);
            if (!$isRecursive && $this->isecho) {
                echo '=' . $expression . "\n";
            }
        }
        // 处理加法和减法
        while (preg_match('/(-?\d+(\.\d+)?)([+\-])(-?\d+(\.\d+)?)/', $expression, $matches)) {
            $res        = $this->basic($matches[0], $scale);
            $expression = str_replace($matches[0], $res, $expression);
            if (!$isRecursive && $this->isecho) {
                echo '=' . $expression . "\n";
            }
        }
        // 返回计算结果
        return $expression;
    }

    // 基本的四则运算
    /**
     * @param $expression   // 基本的四则运算表达式
     * @param $scale    // 精度
     */
    public function basic($expression, $scale = '') {
        $scale = $scale ?: $this->scale;
        // 使用正则表达式匹配表达式中的两个操作数和一个运算符
        if (!preg_match('/^(-?\d+(\.\d+)?)([\/*+-]|(\*\*))(-?\d+(\.\d+)?)$/', $expression, $matches)) {
            throw new \InvalidArgumentException('表达式错误,不符合基本的四则运算:' . $expression);
        }
        // dump($matches);
        // 根据运算符调用对应的 bcmath 函数
        $operator = $matches[3];
        $a        = strval($matches[1]);
        $b        = strval($matches[5]);
        // if ($this->isecho) {
        //     echo '【处理运算符】' . $a . $operator . $b . "\n";
        // }
        try {
            switch ($operator) {
            case '+':
                return bcadd($a, $b, $scale);
            case '-':
                return bcsub($a, $b, $scale);
            case '*':
                return bcmul($a, $b, $scale);
            case '/':
                if ($b == 0) {
                    throw new \InvalidArgumentException('除数不能为零:' . $a . $operator . $b);
                }
                return bcdiv($a, $b, $scale);
            case '**':
                if (strpos($b, '.') !== false) {
                    if ((int) $b == $b) {
                        $b = (int) $b;
                    } else {
                        throw new \InvalidArgumentException('指数不能为小数:' . $a . $operator . $b);
                    }
                }
                return bcpow($a, $b, $scale);
            default:
                throw new \InvalidArgumentException('未知的运算符:' . $a . $operator . $b);
            }
        } catch (\Exception $e) {
            throw new \InvalidArgumentException($e->getMessage());
        }
    }

}

class CComponent
{
    private $_e;
    private $_m;

    /**
     * Returns a property value, an event handler list or a behavior based on its name.
     * Do not call this method. This is a PHP magic method that we override
     * to allow using the following syntax to read a property or obtain event handlers:
     * <pre>
     * $value=$component->propertyName;
     * $handlers=$component->eventName;
     * </pre>
     * @param string $name the property name or event name
     * @return mixed the property value, event handlers attached to the event, or the named behavior
     * @throws CException if the property or event is not defined
     * @see __set
     */
    public function __get($name)
    {
        $getter='get'.$name;
        if(method_exists($this,$getter))
            return $this->$getter();
        elseif(strncasecmp($name,'on',2)===0 && method_exists($this,$name))
        {
            // duplicating getEventHandlers() here for performance
            $name=strtolower($name);
            if(!isset($this->_e[$name]))
                $this->_e[$name]=new CList;
            return $this->_e[$name];
        }
        elseif(isset($this->_m[$name]))
            return $this->_m[$name];
        elseif(is_array($this->_m))
        {
            foreach($this->_m as $object)
            {
                if($object->getEnabled() && (property_exists($object,$name) || $object->canGetProperty($name)))
                    return $object->$name;
            }
        }
        throw new CException(Yii::t('yii','Property "{class}.{property}" is not defined.',
            array('{class}'=>get_class($this), '{property}'=>$name)));
    }

    /**
     * Sets value of a component property.
     * Do not call this method. This is a PHP magic method that we override
     * to allow using the following syntax to set a property or attach an event handler
     * <pre>
     * $this->propertyName=$value;
     * $this->eventName=$callback;
     * </pre>
     * @param string $name the property name or the event name
     * @param mixed $value the property value or callback
     * @return mixed
     * @throws CException if the property/event is not defined or the property is read only.
     * @see __get
     */
    public function __set($name,$value)
    {
        $setter='set'.$name;
        if(method_exists($this,$setter))
            return $this->$setter($value);
        elseif(strncasecmp($name,'on',2)===0 && method_exists($this,$name))
        {
            // duplicating getEventHandlers() here for performance
            $name=strtolower($name);
            if(!isset($this->_e[$name]))
                $this->_e[$name]=new CList;
            return $this->_e[$name]->add($value);
        }
        elseif(is_array($this->_m))
        {
            foreach($this->_m as $object)
            {
                if($object->getEnabled() && (property_exists($object,$name) || $object->canSetProperty($name)))
                    return $object->$name=$value;
            }
        }
        if(method_exists($this,'get'.$name))
            throw new CException(Yii::t('yii','Property "{class}.{property}" is read only.',
                array('{class}'=>get_class($this), '{property}'=>$name)));
        else
            throw new CException(Yii::t('yii','Property "{class}.{property}" is not defined.',
                array('{class}'=>get_class($this), '{property}'=>$name)));
    }

    /**
     * Checks if a property value is null.
     * Do not call this method. This is a PHP magic method that we override
     * to allow using isset() to detect if a component property is set or not.
     * @param string $name the property name or the event name
     * @return boolean
     */
    public function __isset($name)
    {
        $getter='get'.$name;
        if(method_exists($this,$getter))
            return $this->$getter()!==null;
        elseif(strncasecmp($name,'on',2)===0 && method_exists($this,$name))
        {
            $name=strtolower($name);
            return isset($this->_e[$name]) && $this->_e[$name]->getCount();
        }
        elseif(is_array($this->_m))
        {
             if(isset($this->_m[$name]))
                 return true;
            foreach($this->_m as $object)
            {
                if($object->getEnabled() && (property_exists($object,$name) || $object->canGetProperty($name)))
                    return $object->$name!==null;
            }
        }
        return false;
    }

    /**
     * Sets a component property to be null.
     * Do not call this method. This is a PHP magic method that we override
     * to allow using unset() to set a component property to be null.
     * @param string $name the property name or the event name
     * @throws CException if the property is read only.
     * @return mixed
     */
    public function __unset($name)
    {
        $setter='set'.$name;
        if(method_exists($this,$setter))
            $this->$setter(null);
        elseif(strncasecmp($name,'on',2)===0 && method_exists($this,$name))
            unset($this->_e[strtolower($name)]);
        elseif(is_array($this->_m))
        {
            if(isset($this->_m[$name]))
                $this->detachBehavior($name);
            else
            {
                foreach($this->_m as $object)
                {
                    if($object->getEnabled())
                    {
                        if(property_exists($object,$name))
                            return $object->$name=null;
                        elseif($object->canSetProperty($name))
                            return $object->$setter(null);
                    }
                }
            }
        }
        elseif(method_exists($this,'get'.$name))
            throw new CException(Yii::t('yii','Property "{class}.{property}" is read only.',
                array('{class}'=>get_class($this), '{property}'=>$name)));
    }

    /**
     * Calls the named method which is not a class method.
     * Do not call this method. This is a PHP magic method that we override
     * to implement the behavior feature.
     * @param string $name the method name
     * @param array $parameters method parameters
     * @throws CException if current class and its behaviors do not have a method or closure with the given name
     * @return mixed the method return value
     */
    public function __call($name,$parameters)
    {
        if($this->_m!==null)
        {
            foreach($this->_m as $object)
            {
                if($object->getEnabled() && method_exists($object,$name))
                    return call_user_func_array(array($object,$name),$parameters);
            }
        }
        if(class_exists('Closure', false) && ($this->canGetProperty($name) || property_exists($this, $name)) && $this->$name instanceof Closure)
            return call_user_func_array($this->$name, $parameters);
        throw new CException(Yii::t('yii','{class} and its behaviors do not have a method or closure named "{name}".',
            array('{class}'=>get_class($this), '{name}'=>$name)));
    }

    /**
     * Returns the named behavior object.
     * The name 'asa' stands for 'as a'.
     * @param string $behavior the behavior name
     * @return IBehavior the behavior object, or null if the behavior does not exist
     */
    public function asa($behavior)
    {
        return isset($this->_m[$behavior]) ? $this->_m[$behavior] : null;
    }

    /**
     * Attaches a list of behaviors to the component.
     * Each behavior is indexed by its name and should be an instance of
     * {@link IBehavior}, a string specifying the behavior class, or an
     * array of the following structure:
     * <pre>
     * array(
     *     'class'=>'path.to.BehaviorClass',
     *     'property1'=>'value1',
     *     'property2'=>'value2',
     * )
     * </pre>
     * @param array $behaviors list of behaviors to be attached to the component
     */
    public function attachBehaviors($behaviors)
    {
        foreach($behaviors as $name=>$behavior)
            $this->attachBehavior($name,$behavior);
    }

    /**
     * Detaches all behaviors from the component.
     */
    public function detachBehaviors()
    {
        if($this->_m!==null)
        {
            foreach($this->_m as $name=>$behavior)
                $this->detachBehavior($name);
            $this->_m=null;
        }
    }

    /**
     * Attaches a behavior to this component.
     * This method will create the behavior object based on the given
     * configuration. After that, the behavior object will be initialized
     * by calling its {@link IBehavior::attach} method.
     * @param string $name the behavior's name. It should uniquely identify this behavior.
     * @param mixed $behavior the behavior configuration. This is passed as the first
     * parameter to {@link YiiBase::createComponent} to create the behavior object.
     * You can also pass an already created behavior instance (the new behavior will replace an already created
     * behavior with the same name, if it exists).
     * @return IBehavior the behavior object
     */
    public function attachBehavior($name,$behavior)
    {
        if(!($behavior instanceof IBehavior))
            $behavior=Yii::createComponent($behavior);
        $behavior->setEnabled(true);
        $behavior->attach($this);
        return $this->_m[$name]=$behavior;
    }

    /**
     * Detaches a behavior from the component.
     * The behavior's {@link IBehavior::detach} method will be invoked.
     * @param string $name the behavior's name. It uniquely identifies the behavior.
     * @return IBehavior the detached behavior. Null if the behavior does not exist.
     */
    public function detachBehavior($name)
    {
        if(isset($this->_m[$name]))
        {
            $this->_m[$name]->detach($this);
            $behavior=$this->_m[$name];
            unset($this->_m[$name]);
            return $behavior;
        }
    }

    /**
     * Enables all behaviors attached to this component.
     */
    public function enableBehaviors()
    {
        if($this->_m!==null)
        {
            foreach($this->_m as $behavior)
                $behavior->setEnabled(true);
        }
    }

    /**
     * Disables all behaviors attached to this component.
     */
    public function disableBehaviors()
    {
        if($this->_m!==null)
        {
            foreach($this->_m as $behavior)
                $behavior->setEnabled(false);
        }
    }

    /**
     * Enables an attached behavior.
     * A behavior is only effective when it is enabled.
     * A behavior is enabled when first attached.
     * @param string $name the behavior's name. It uniquely identifies the behavior.
     */
    public function enableBehavior($name)
    {
        if(isset($this->_m[$name]))
            $this->_m[$name]->setEnabled(true);
    }

    /**
     * Disables an attached behavior.
     * A behavior is only effective when it is enabled.
     * @param string $name the behavior's name. It uniquely identifies the behavior.
     */
    public function disableBehavior($name)
    {
        if(isset($this->_m[$name]))
            $this->_m[$name]->setEnabled(false);
    }

    /**
     * Determines whether a property is defined.
     * A property is defined if there is a getter or setter method
     * defined in the class. Note, property names are case-insensitive.
     * @param string $name the property name
     * @return boolean whether the property is defined
     * @see canGetProperty
     * @see canSetProperty
     */
    public function hasProperty($name)
    {
        return method_exists($this,'get'.$name) || method_exists($this,'set'.$name);
    }

    /**
     * Determines whether a property can be read.
     * A property can be read if the class has a getter method
     * for the property name. Note, property name is case-insensitive.
     * @param string $name the property name
     * @return boolean whether the property can be read
     * @see canSetProperty
     */
    public function canGetProperty($name)
    {
        return method_exists($this,'get'.$name);
    }

    /**
     * Determines whether a property can be set.
     * A property can be written if the class has a setter method
     * for the property name. Note, property name is case-insensitive.
     * @param string $name the property name
     * @return boolean whether the property can be written
     * @see canGetProperty
     */
    public function canSetProperty($name)
    {
        return method_exists($this,'set'.$name);
    }

    /**
     * Determines whether an event is defined.
     * An event is defined if the class has a method named like 'onXXX'.
     * Note, event name is case-insensitive.
     * @param string $name the event name
     * @return boolean whether an event is defined
     */
    public function hasEvent($name)
    {
        return !strncasecmp($name,'on',2) && method_exists($this,$name);
    }

    /**
     * Checks whether the named event has attached handlers.
     * @param string $name the event name
     * @return boolean whether an event has been attached one or several handlers
     */
    public function hasEventHandler($name)
    {
        $name=strtolower($name);
        return isset($this->_e[$name]) && $this->_e[$name]->getCount()>0;
    }

    /**
     * Returns the list of attached event handlers for an event.
     * @param string $name the event name
     * @return CList list of attached event handlers for the event
     * @throws CException if the event is not defined
     */
    public function getEventHandlers($name)
    {
        if($this->hasEvent($name))
        {
            $name=strtolower($name);
            if(!isset($this->_e[$name]))
                $this->_e[$name]=new CList;
            return $this->_e[$name];
        }
        else
            throw new CException(Yii::t('yii','Event "{class}.{event}" is not defined.',
                array('{class}'=>get_class($this), '{event}'=>$name)));
    }

    /**
     * Attaches an event handler to an event.
     *
     * An event handler must be a valid PHP callback, i.e., a string referring to
     * a global function name, or an array containing two elements with
     * the first element being an object and the second element a method name
     * of the object.
     *
     * An event handler must be defined with the following signature,
     * <pre>
     * function handlerName($event) {}
     * </pre>
     * where $event includes parameters associated with the event.
     *
     * This is a convenient method of attaching a handler to an event.
     * It is equivalent to the following code:
     * <pre>
     * $component->getEventHandlers($eventName)->add($eventHandler);
     * </pre>
     *
     * Using {@link getEventHandlers}, one can also specify the execution order
     * of multiple handlers attaching to the same event. For example:
     * <pre>
     * $component->getEventHandlers($eventName)->insertAt(0,$eventHandler);
     * </pre>
     * makes the handler to be invoked first.
     *
     * @param string $name the event name
     * @param callback $handler the event handler
     * @throws CException if the event is not defined
     * @see detachEventHandler
     */
    public function attachEventHandler($name,$handler)
    {
        $this->getEventHandlers($name)->add($handler);
    }

    /**
     * Detaches an existing event handler.
     * This method is the opposite of {@link attachEventHandler}.
     * @param string $name event name
     * @param callback $handler the event handler to be removed
     * @return boolean if the detachment process is successful
     * @see attachEventHandler
     */
    public function detachEventHandler($name,$handler)
    {
        if($this->hasEventHandler($name))
            return $this->getEventHandlers($name)->remove($handler)!==false;
        else
            return false;
    }

    /**
     * Raises an event.
     * This method represents the happening of an event. It invokes
     * all attached handlers for the event.
     * @param string $name the event name
     * @param CEvent $event the event parameter
     * @throws CException if the event is undefined or an event handler is invalid.
     */
    public function raiseEvent($name,$event)
    {
        $name=strtolower($name);
        if(isset($this->_e[$name]))
        {
            foreach($this->_e[$name] as $handler)
            {
                if(is_string($handler))
                    call_user_func($handler,$event);
                elseif(is_callable($handler,true))
                {
                    if(is_array($handler))
                    {
                        // an array: 0 - object, 1 - method name
                        list($object,$method)=$handler;
                        if(is_string($object))    // static method call
                            call_user_func($handler,$event);
                        elseif(method_exists($object,$method))
                            $object->$method($event);
                        else
                            throw new CException(Yii::t('yii','Event "{class}.{event}" is attached with an invalid handler "{handler}".',
                                array('{class}'=>get_class($this), '{event}'=>$name, '{handler}'=>$handler[1])));
                    }
                    else // PHP 5.3: anonymous function
                        call_user_func($handler,$event);
                }
                else
                    throw new CException(Yii::t('yii','Event "{class}.{event}" is attached with an invalid handler "{handler}".',
                        array('{class}'=>get_class($this), '{event}'=>$name, '{handler}'=>gettype($handler))));
                // stop further handling if param.handled is set true
                if(($event instanceof CEvent) && $event->handled)
                    return;
            }
        }
        elseif(YII_DEBUG && !$this->hasEvent($name))
            throw new CException(Yii::t('yii','Event "{class}.{event}" is not defined.',
                array('{class}'=>get_class($this), '{event}'=>$name)));
    }

    /**
     * Evaluates a PHP expression or callback under the context of this component.
     *
     * Valid PHP callback can be class method name in the form of
     * array(ClassName/Object, MethodName), or anonymous function (only available in PHP 5.3.0 or above).
     *
     * If a PHP callback is used, the corresponding function/method signature should be
     * <pre>
     * function foo($param1, $param2, ..., $component) { ... }
     * </pre>
     * where the array elements in the second parameter to this method will be passed
     * to the callback as $param1, $param2, ...; and the last parameter will be the component itself.
     *
     * If a PHP expression is used, the second parameter will be "extracted" into PHP variables
     * that can be directly accessed in the expression. See {@link http://us.php.net/manual/en/function.extract.php PHP extract}
     * for more details. In the expression, the component object can be accessed using $this.
     *
     * A PHP expression can be any PHP code that has a value. To learn more about what an expression is,
     * please refer to the {@link http://www.php.net/manual/en/language.expressions.php php manual}.
     *
     * @param mixed $_expression_ a PHP expression or PHP callback to be evaluated.
     * @param array $_data_ additional parameters to be passed to the above expression/callback.
     * @return mixed the expression result
     * @since 1.1.0
     */
    public function evaluateExpression($_expression_,$_data_=array())
    {
        if(is_string($_expression_))
        {
            extract($_data_);
            try
            {
                return eval('return ' . $_expression_ . ';');
            }
            catch (ParseError $e)
            {
                return false;
            }
        }
        else
        {
            $_data_[]=$this;
            return call_user_func_array($_expression_, array_values($_data_));
        }
    }
}

在PHP应用中,超时时间的设置对于应用的性能和稳定性至关重要。超时时间配置不当可能导致应用响应缓慢、资源占用过高,甚至引发服务崩溃。本文将详细解析PHP配置文件php.ini和php-fpm.conf中的超时时间设置,帮助读者深入理解这些设置的作用、影响以及如何合理配置。

一、php.ini中的超时时间设置

max_execution_time
max_execution_time 是php.ini中的一个重要设置,它定义了PHP脚本的最大执行时间。当脚本运行时间超过这个值时,PHP会终止脚本的执行并返回一个致命错误。这个设置对于防止恶意脚本或无限循环脚本占用过多资源非常有用。

默认情况下,max_execution_time 的值为30秒。在实际应用中,我们可以根据应用的需求和性能要求来合理设置这个值。需要注意的是,这个设置只影响PHP脚本本身的执行时间,不包括脚本执行过程中可能发生的数据库查询、文件操作等外部操作的时间。

set_time_limit() 可以在php代码中更改执行时间 max_execution_time 的定义。

implicit_flush
implicit_flush 是一个影响输出缓冲设置的选项。当implicit_flush设置为On时,PHP会在每次输出内容时自动刷新输出缓冲区,这样可以确保用户能够实时看到输出的内容。然而,频繁的刷新输出缓冲区可能会降低应用的性能。因此,在需要实时输出内容的情况下,我们可以将implicit_flush设置为On;在其他情况下,建议将其设置为Off以提高性能。

二、php-fpm.conf中的超时时间设置

request_terminate_timeout
[www] 范围
request_terminate_timeout 是php-fpm.conf中的一个设置,它定义了PHP-FPM进程在处理请求时的最大执行时间。当请求的处理时间超过这个值时,PHP-FPM会强制终止该请求并返回一个错误。这个设置有助于防止长时间运行的请求占用过多的资源。

默认情况下,request_terminate_timeout 的值为0,表示禁用超时限制。在实际应用中,我们可以根据应用的需求和性能要求来合理设置这个值。需要注意的是,这个设置的值应该大于max_execution_time的值,以确保PHP脚本有足够的时间来执行。

process_control_timeout
php-fpm 全局
process_control_timeout 是php-fpm.conf中的另一个重要设置,它定义了PHP-FPM进程控制操作的超时时间。当PHP-FPM需要启动、重启或关闭子进程时,如果超过了这个时间限制,PHP-FPM会放弃该操作并返回一个错误。这个设置有助于防止PHP-FPM进程控制操作因为各种原因(如资源不足、网络延迟等)而无限期地等待。

默认情况下,process_control_timeout 的值为0,表示禁用超时限制。然而,在实际应用中,我们建议设置一个合理的值来确保PHP-FPM进程控制操作的稳定性和可靠性。

三、总结

通过本文的解析,我们深入了解了PHP配置文件php.ini和php-fpm.conf中的超时时间设置。这些设置对于提高PHP应用的性能和稳定性具有重要意义。在实际应用中,我们应该根据应用的需求和性能要求来合理配置这些值,以确保应用的正常运行和高效性能。同时,我们还需要关注这些设置可能带来的潜在风险和问题,并采取相应的措施来避免和解决这些问题。

希望本文能够帮助读者更好地理解PHP配置文件中的超时时间设置,并为实际应用中的配置提供参考和指导。

管理面板
国内版
宝塔最新的免费面板:http://www.bt.cn/(国外版本 :https://aapanel.com

AMH – 4.2版免费:http://amh.sh/

WDCP 老牌免费面板:http://www.wdlinux.cn/bbs/(近来爆出严重安全漏洞)

Kangle老牌免费面板:http://www.kanglesoft.com/

自己的路 – 支持freeBSD:http://www.zijidelu.org/

国外版
VestaCP:http://vestacp.com/ (比较推荐的面板,自带中文)

Kloxo-MR:https://github.com/mustafaramadhan/kloxo/ (7.0真的很强大,很好看,很实用,有中文包)

Webmin/Virtualmin:http://www.webmin.com/virtualmin.html (很稳定,很安全,自带中文)

Ispconfig:https://github.com/dclardy64/ISPConfig-3-Debian-Installer (官网没看懂这是一键包,有中文包)

i-MSCP:http://i-mscp.net/ (简单易用,自带中文)

EasySCP:http://www.easyscp.net/ (和i-MSCP一样来自Ispconfig,自带中文)

Ajenti:http://ajenti.org/ (轻量级,类似Webmin,自带中文)

zPanel(sentora):http://www.zpanelcp.com/ http://www.sentora.org/(支持win,有中文包)

centos webpanel:http://centos-webpanel.com/ (据说比较有发展前途)

Froxlor:http://www.froxlor.org/ (很轻量的,适应各种环境)

AlternC:https://alternc.org/ (简单)

Easy Hosting Control Panel:http://ehcp.net/ (还不错的面板,有第三方汉化包)

CyberPanel面板:http://docs.cyberpanel.net/doku.php (目前只支持Centos 7.x)

宝塔英文版?http://www.aapanel.com

runcloud.io面板:https://runcloud.io (有免费版和付费版)

froxlor面板:https://www.froxlor.org/ (面板没有汉化)

一键安装包
国内版
http://lnmp.org/ (用的人很多,适应性很强)

https://oneinstack.com/ (用户也很多,博主一直使用这个)

http://teddysun.com/lamp (很好用的LAMP一键包) http://teddysun.com/lamp-yum (适合小内存≥64M)

http://bbs.aliyun.com/read/151729.html (阿里云论坛看到的)

http://blog.linuxeye.com/31.html (多种配置,软件较新)

http://lnmpp.net/ (支持postgresql,支持ARM)

http://www.hhvmc.com/thread-17-1-1.html (有hhvm的一键包)

http://shuang.ca/llnmp/ http://llsmp.cn/(有LiteSpeed的一键包)

https://www.lxconfig.com/thread-69-1-1.html (有openresty的一键包)

http://blog.7qy.com/html/1575.html (有cherokee的一键包)

http://lamp.phpstudy.net/ (有Lighttpd的一键包)

http://www.upupw.net/ (Windows平台环境搭建)

https://www.appnode.com (免费版不支持面板)

http://www.ltmp.cc/ (LTMP支持CentOS/RadHat)

http://bet.xrbk.top/ (BET面板 支持CentOS)

国外版
http://centminmod.com/ (据说很适合wordpress)

https://vpssim.com/ (很强大的一键包)

http://tuxlite.com/ (适用于Debian系列)

https://github.com/Xeoncross/lowendscript (lowendscript演变来的)

https://github.com/alexandreteles/monkeyServer(Monkey Web Server轻量级的web服务器) 作者:账号已注销 https://www.bilibili.com/read/cv20507364/

推荐使用轮子:

hiprint 打印JS库 打印设计器
http://hiprint.io/

nop/bookjs-eazy

只需专注用H5构件你的PDF内容,而无需关心分页及内容截断问题,内容满了,自动换页,支持预览、WEB打印、页码/目录、自定义页眉页脚。
https://gitee.com/wuxue107/bookjs-eazy

设置打印宽度计算方式
一般的分辨率为XX像素/英寸,其中一英寸为25.4毫米。
所以一毫米的像素数就为XX/25.4。现在的工作就是求XX的值了,把XX的值求出来以后,
直接用XX/25.4 * 210就得到A4纸的像素宽了。

A4纸的尺寸是210mm×297mm。
分辨率是72像素/英寸时,A4纸的尺寸的图像的像素是595×842(推荐用这个大小比例)。
分辨率是150像素/英寸时,A4纸的尺寸的图像的像素是1240×1754。
分辨率是300像素/英寸时,A4纸的尺寸的图像的像素是2479×3508。
选择不同的分辨率图像像素大小也会随之变化。

我是用下面的转换公式,将A4纸转为在屏幕中的分辨率

页边距: 0.75 inch
A4: 8.27x11.69 inch
打印机DPI:600DPI
屏幕DPI : 96DPI
width = (8.27 - 0.75 2) 96 / 600 = 650 px
height = (11.69 - 0.75 2) 96 / 600 = 978 px

所以,当

的width=650px, height=978px时,用IE 打印时,刚好能打印一页的A4纸.

@media print {
        #print-content {
            width: 7.52in;
        }
    }

原文链接:https://segmentfault.com/a/1190000016132057

目前正在做浏览器端采用js方式实现打印这么一个功能,JS打印实现的方法很多,但是兼容各个浏览器实现打印预览的功能有些棘手,现将实现的内容及遇到的问题记录下来,希望有大牛看到所提的问题后可以给予解答,在此感谢啦。

1.JS实现打印的方式
方式一:window.print()
window.print();会弹出打印对话框,打印的是window.document.body.innerHTML中的内容,下面是从网上摘到的一个局部打印的例子,该例子的不足是打印会修改页面的内容。

<!DOCTYPE html>  
<html>  
<head>  
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />  
<title>局部打印案例</title>  
<script type="text/javascript">     
    function doPrint() {      
        bdhtml=window.document.body.innerHTML;      
        sprnstr="<!--startprint-->";      
        eprnstr="<!--endprint-->";      
        prnhtml=bdhtml.substr(bdhtml.indexOf(sprnstr)+17);      
        prnhtml=prnhtml.substring(0,prnhtml.indexOf(eprnstr));      
        window.document.body.innerHTML=prnhtml;   
        window.print();      
}      
</script>  
</head>  
  
<body>  
<p>1不需要打印的地方</p>  
<p>2这里不要打印啊</p>  
<!--startprint--><!--注意要加上html里star和end的这两个标记-->  
<h1>打印标题</h1>  
<p>打印内容~~</p>  
<!--endprint-->  
<button type="button" onclick="doPrint()">打印</button>  
<p>不打印的地方啊哈哈哈哈</p>  
<p>2</p>  
</body>  
</html>  

方式二:使用html 标签引入Webbrowser控件
这种方式是其只兼容IE,其他浏览器不可使用,同时IE10以下的浏览器才可以使用,调用方式如下:

<body>  
    <object id="WebBrowser" classid=CLSID:8856F961-340A-11D0-A96B-00C04FD705A2 height="0" width="0"> </object>  
</body>  
<script>  
    WebBrowser.ExecWB(1,1)  //打开   
    WebBrowser.ExecWB(2,1)  //关闭现在所有的IE窗口,并打开一个新窗口   
    WebBrowser.ExecWB(4,1)  //保存网页  
    //--------------- 常用 ---------------      
    WebBrowser.ExecWB(6,1)  //打印   
    WebBrowser.ExecWB(7,1)  //打印预览   
    WebBrowser.ExecWB(8,1)  //打印页面设置   
    //-------------------------------------   
    WebBrowser.ExecWB(10,1) //查看页面属性   
    WebBrowser.ExecWB(15,1) //撤销   
    WebBrowser.ExecWB(17,1) //全选   
    WebBrowser.ExecWB(22,1) //刷新   
    WebBrowser.ExecWB(45,1) //关闭窗体无提示  
</script>  
<body>
    <object id="WebBrowser" classid=CLSID:8856F961-340A-11D0-A96B-00C04FD705A2 height="0" width="0"> </object>
</body>
<script>
    WebBrowser.ExecWB(1,1)  //打开 
    WebBrowser.ExecWB(2,1)  //关闭现在所有的IE窗口,并打开一个新窗口 
    WebBrowser.ExecWB(4,1)  //保存网页
    //--------------- 常用 ---------------    
    WebBrowser.ExecWB(6,1)  //打印 
    WebBrowser.ExecWB(7,1)  //打印预览 
    WebBrowser.ExecWB(8,1)  //打印页面设置 
    //-------------------------------------    
    WebBrowser.ExecWB(10,1) //查看页面属性 
    WebBrowser.ExecWB(15,1) //撤销 
    WebBrowser.ExecWB(17,1) //全选 
    WebBrowser.ExecWB(22,1) //刷新 
    WebBrowser.ExecWB(45,1) //关闭窗体无提示
</script>

这种方式优势是在IE下可以弹出打印预览,这是打印很人性化的功能,但是遗憾的是高版本的IE浏览器不支持WebBrowser了

方式三:采用document.execCommand(”print”)
该方式也兼容各个版本的浏览器,同window.print()一样,其启动的是打印对话框,chrome的打印对话框自带预览功能,但是IE、火狐仅仅只弹出打印设置对话框,没有预览功能。
方式四:采用JQuery插件
使用jQuery浏览插件可以很方便的进行局部打印,常用的插件有:

1)jquery.print.js 下载地址:https://github.com/DoersGuild/jQuery.print

2)jquery.print-preview.js 下载地址:https://github.com/DoersGuild/jQuery.print

这两种方式使用都很简单,1)通过$("#id").print(/*options*/);调用;2)通过$('#id').printArea(/options/); 其中的option可选项可以在下载地址下载下来后看示例代码,一般options不用传即可,示例代码如下:

<html>  
<head>  
<meta http-equiv=Content-Type content="text/html; charset=utf-8">  
<title>JQuery打印</title>  
<script type="text/javascript" src="./js/jquery-3.1.1.min.js"></script>  
<script language="javascript" src="./js/jquery.print.js"></script>  
</head>  
  
<body style='margin:0 auto;text-align:center;'>  
<button id='button_print' name='button_print' onclick="javascript:printit()>打印</button>  
<div id='ganburenmianbaio' class=WordSection1 style='width:750px;margin:0 auto;text-align:center;vertical-align: middle;'>  
</div>  
</body>  
<script language="javascript">  
function printit(){  
    $("#ganburenmianbaio").print({iframe:true,prepend:'<br/>'});  
}  
</script>  
</html>  
<html>
<head>
<meta http-equiv=Content-Type content="text/html; charset=utf-8">
<title>JQuery打印</title>
<script type="text/javascript" src="./js/jquery-3.1.1.min.js"></script>
<script language="javascript" src="./js/jquery.print.js"></script>
</head>
 
<body style='margin:0 auto;text-align:center;'>
<button id='button_print' name='button_print' onclick="javascript:printit()>打印</button>
<div id='ganburenmianbaio' class=WordSection1 style='width:750px;margin:0 auto;text-align:center;vertical-align: middle;'>
</div>
</body>
<script language="javascript">
function printit(){
    $("#ganburenmianbaio").print({iframe:true,prepend:'<br/>'});
}
</script>
</html>

方式五:采用浏览器打印第三方插件
该方式需要用户浏览器安装相关的第三方插件,用户体验不好,故在此不细述了。

2.打印预览
chrome浏览器、win10自带的IE浏览器 调用打印弹出的打印设置界面中包含打印预览部分,故其通过上面的打印函数的调用即可实现。

IE9以后的版本、火狐不支持webbrowser控件了,JS调用不了浏览器的打印预览的功能,我们只能用iframe模拟打印预览的对话框,将需要打印的内容显示在该对话框中,然后在调用打印的功能实现打印。

1)jquery打印预览插件
jquery.print-preview.js 下载地址:https://github.com/etimbo/jquery-print-preview-plugin

其实现的效果如下图(其自动的示例代码)

2)webbrowser控件打印预览
IE8及以下版本可以调用WebBrowser.ExecWB(7,1) 函数弹出浏览器的打印预览对话框,采用该函数的好处是 用户可以在打印预览对话框中 调整页边距、页眉、页脚;

下面贴出的是设置页边距、页眉、页脚的JS代码

//取得页面打印设置的原参数数据     
function PageSetup_temp(){     
    try     
    {     
       var Wsh=new ActiveXObject("WScript.Shell");     
       HKEY_Key="header";     
        //取得页眉默认值     
       head = Wsh.RegRead(HKEY_Root+HKEY_Path+HKEY_Key);     
       HKEY_Key="footer";     
        //取得页脚默认值     
       foot = Wsh.RegRead(HKEY_Root+HKEY_Path+HKEY_Key);     
       HKEY_Key="margin_bottom";     
        //取得下页边距     
       bottom = Wsh.RegRead(HKEY_Root+HKEY_Path+HKEY_Key);     
       HKEY_Key="margin_left";     
        //取得左页边距     
       left = Wsh.RegRead(HKEY_Root+HKEY_Path+HKEY_Key);     
       HKEY_Key="margin_right";     
        //取得右页边距     
       right = Wsh.RegRead(HKEY_Root+HKEY_Path+HKEY_Key);     
       HKEY_Key="margin_top";     
        //取得上页边距     
       top = Wsh.RegRead(HKEY_Root+HKEY_Path+HKEY_Key);     
    }     
    catch(e){     
         //alert("不允许ActiveX控件");     
    }     
}  



//设置网页打印的页眉页脚和页边距,注册表里的单位是英寸,打印设置中是毫米,1英寸=25.4毫米     
function PageSetup_Null(){     
    try     
    {     
       var Wsh=new ActiveXObject("WScript.Shell");     
       HKEY_Key="header";     
        //设置页眉(为空)     
       Wsh.RegWrite(HKEY_Root+HKEY_Path+HKEY_Key,"");     
       HKEY_Key="footer";     
        //设置页脚(为空)     
       Wsh.RegWrite(HKEY_Root+HKEY_Path+HKEY_Key,"");     
       HKEY_Key="margin_bottom";     
        //设置下页边距(0)     
       Wsh.RegWrite(HKEY_Root+HKEY_Path+HKEY_Key,"0.6");     
       HKEY_Key="margin_left";     
        //设置左页边距(0)     
       Wsh.RegWrite(HKEY_Root+HKEY_Path+HKEY_Key,"0.3");     
       HKEY_Key="margin_right";     
        //设置右页边距(0)     
       Wsh.RegWrite(HKEY_Root+HKEY_Path+HKEY_Key,"0.3");     
       HKEY_Key="margin_top";     
        //设置上页边距(8)     
       Wsh.RegWrite(HKEY_Root+HKEY_Path+HKEY_Key,"0.6");     
    }     
    catch(e){     
         //alert("不允许ActiveX控件");     
    }     
}     
  
//设置网页打印的页眉页脚和页边距为默认值     
function PageSetup_Default(){        
    try     
    {     
       var Wsh=new ActiveXObject("WScript.Shell");     
       HKEY_Key="header";     
       HKEY_Key="header";     
        //还原页眉     
       Wsh.RegWrite(HKEY_Root+HKEY_Path+HKEY_Key,head);     
       HKEY_Key="footer";     
        //还原页脚     
       Wsh.RegWrite(HKEY_Root+HKEY_Path+HKEY_Key,foot);     
       HKEY_Key="margin_bottom";     
        //还原下页边距     
       Wsh.RegWrite(HKEY_Root+HKEY_Path+HKEY_Key,bottom);     
       HKEY_Key="margin_left";     
        //还原左页边距     
       Wsh.RegWrite(HKEY_Root+HKEY_Path+HKEY_Key,left);     
       HKEY_Key="margin_right";     
        //还原右页边距     
       Wsh.RegWrite(HKEY_Root+HKEY_Path+HKEY_Key,right);     
       HKEY_Key="margin_top";     
        //还原上页边距     
       Wsh.RegWrite(HKEY_Root+HKEY_Path+HKEY_Key,top);     
    }     
    catch(e){     
         //alert("不允许ActiveX控件");     
    }     
}  
//取得页面打印设置的原参数数据   
function PageSetup_temp(){   
    try   
    {   
       var Wsh=new ActiveXObject("WScript.Shell");   
       HKEY_Key="header";   
        //取得页眉默认值   
       head = Wsh.RegRead(HKEY_Root+HKEY_Path+HKEY_Key);   
       HKEY_Key="footer";   
        //取得页脚默认值   
       foot = Wsh.RegRead(HKEY_Root+HKEY_Path+HKEY_Key);   
       HKEY_Key="margin_bottom";   
        //取得下页边距   
       bottom = Wsh.RegRead(HKEY_Root+HKEY_Path+HKEY_Key);   
       HKEY_Key="margin_left";   
        //取得左页边距   
       left = Wsh.RegRead(HKEY_Root+HKEY_Path+HKEY_Key);   
       HKEY_Key="margin_right";   
        //取得右页边距   
       right = Wsh.RegRead(HKEY_Root+HKEY_Path+HKEY_Key);   
       HKEY_Key="margin_top";   
        //取得上页边距   
       top = Wsh.RegRead(HKEY_Root+HKEY_Path+HKEY_Key);   
    }   
    catch(e){   
         //alert("不允许ActiveX控件");   
    }   
}   



//设置网页打印的页眉页脚和页边距,注册表里的单位是英寸,打印设置中是毫米,1英寸=25.4毫米   
function PageSetup_Null(){   
    try   
    {   
       var Wsh=new ActiveXObject("WScript.Shell");   
       HKEY_Key="header";   
        //设置页眉(为空)   
       Wsh.RegWrite(HKEY_Root+HKEY_Path+HKEY_Key,"");   
       HKEY_Key="footer";   
        //设置页脚(为空)   
       Wsh.RegWrite(HKEY_Root+HKEY_Path+HKEY_Key,"");   
       HKEY_Key="margin_bottom";   
        //设置下页边距(0)   
       Wsh.RegWrite(HKEY_Root+HKEY_Path+HKEY_Key,"0.6");   
       HKEY_Key="margin_left";   
        //设置左页边距(0)   
       Wsh.RegWrite(HKEY_Root+HKEY_Path+HKEY_Key,"0.3");   
       HKEY_Key="margin_right";   
        //设置右页边距(0)   
       Wsh.RegWrite(HKEY_Root+HKEY_Path+HKEY_Key,"0.3");   
       HKEY_Key="margin_top";   
        //设置上页边距(8)   
       Wsh.RegWrite(HKEY_Root+HKEY_Path+HKEY_Key,"0.6");   
    }   
    catch(e){   
         //alert("不允许ActiveX控件");   
    }   
}   
 
//设置网页打印的页眉页脚和页边距为默认值   
function PageSetup_Default(){      
    try   
    {   
       var Wsh=new ActiveXObject("WScript.Shell");   
       HKEY_Key="header";   
       HKEY_Key="header";   
        //还原页眉   
       Wsh.RegWrite(HKEY_Root+HKEY_Path+HKEY_Key,head);   
       HKEY_Key="footer";   
        //还原页脚   
       Wsh.RegWrite(HKEY_Root+HKEY_Path+HKEY_Key,foot);   
       HKEY_Key="margin_bottom";   
        //还原下页边距   
       Wsh.RegWrite(HKEY_Root+HKEY_Path+HKEY_Key,bottom);   
       HKEY_Key="margin_left";   
        //还原左页边距   
       Wsh.RegWrite(HKEY_Root+HKEY_Path+HKEY_Key,left);   
       HKEY_Key="margin_right";   
        //还原右页边距   
       Wsh.RegWrite(HKEY_Root+HKEY_Path+HKEY_Key,right);   
       HKEY_Key="margin_top";   
        //还原上页边距   
       Wsh.RegWrite(HKEY_Root+HKEY_Path+HKEY_Key,top);   
    }   
    catch(e){   
         //alert("不允许ActiveX控件");   
    }   
}
使用该函数,会弹出

通过网页修改activex安全设置,添加信任站点,禁用该弹出窗口提示,代码如下:

function activeXControl(){  
        try{  
        var WshShell=new ActiveXObject("WScript.Shell");  
          
        //添加信任站点(http://127.0.0.1)  
        WshShell.RegWrite("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\ZoneMap\\Ranges\\Range100\\","");  
        WshShell.RegWrite("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\ZoneMap\\Ranges\\Range100\\:Range","127.0.0.1");  
        WshShell.RegWrite("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\ZoneMap\\Ranges\\Range100\\http","2","REG_DWORD");  
  
        //修改IE ActiveX安全设置: 1本地Intranet区域  
        WshShell.RegWrite("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\1\\1001","0","REG_DWORD");  
        WshShell.RegWrite("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\1\\1004","0","REG_DWORD");  
        WshShell.RegWrite("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\1\\1200","0","REG_DWORD");  
        WshShell.RegWrite("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\1\\1201","0","REG_DWORD");  
        WshShell.RegWrite("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\1\\1405","0","REG_DWORD");  
        WshShell.RegWrite("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\1\\2201","0","REG_DWORD");  
  
        //修改IE ActiveX安全设置:2受信任的站点区域  
        WshShell.RegWrite("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\2\\1001","0","REG_DWORD");  
        WshShell.RegWrite("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\2\\1004","0","REG_DWORD");  
        WshShell.RegWrite("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\2\\1200","0","REG_DWORD");  
        WshShell.RegWrite("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\2\\1201","0","REG_DWORD");  
        WshShell.RegWrite("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\2\\1405","0","REG_DWORD");  
        WshShell.RegWrite("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\2\\2201","0","REG_DWORD");  
          
        //修改IE ActiveX安全设置:3Internet区域  
        WshShell.RegWrite("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\3\\1001","0","REG_DWORD");  
        WshShell.RegWrite("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\3\\1004","0","REG_DWORD");  
        WshShell.RegWrite("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\3\\1200","0","REG_DWORD");  
        WshShell.RegWrite("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\3\\1201","0","REG_DWORD");  
        WshShell.RegWrite("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\3\\1405","0","REG_DWORD");  
        WshShell.RegWrite("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\3\\2201","0","REG_DWORD");  
  
        //禁用Winxp弹出窗口阻止程序  
        WshShell.RegWrite("HKEY_CURRENT_USER\\Software\\Microsoft\\Internet Explorer\\New Windows\\PopupMgr","no");  
    }catch(e){     
         //alert("不允许ActiveX控件");     
    }     
}  
function activeXControl(){
        try{
        var WshShell=new ActiveXObject("WScript.Shell");
        
        //添加信任站点(http://127.0.0.1)
        WshShell.RegWrite("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\ZoneMap\\Ranges\\Range100\\","");
        WshShell.RegWrite("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\ZoneMap\\Ranges\\Range100\\:Range","127.0.0.1");
        WshShell.RegWrite("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\ZoneMap\\Ranges\\Range100\\http","2","REG_DWORD");
 
        //修改IE ActiveX安全设置: 1本地Intranet区域
        WshShell.RegWrite("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\1\\1001","0","REG_DWORD");
        WshShell.RegWrite("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\1\\1004","0","REG_DWORD");
        WshShell.RegWrite("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\1\\1200","0","REG_DWORD");
        WshShell.RegWrite("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\1\\1201","0","REG_DWORD");
        WshShell.RegWrite("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\1\\1405","0","REG_DWORD");
        WshShell.RegWrite("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\1\\2201","0","REG_DWORD");
 
        //修改IE ActiveX安全设置:2受信任的站点区域
        WshShell.RegWrite("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\2\\1001","0","REG_DWORD");
        WshShell.RegWrite("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\2\\1004","0","REG_DWORD");
        WshShell.RegWrite("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\2\\1200","0","REG_DWORD");
        WshShell.RegWrite("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\2\\1201","0","REG_DWORD");
        WshShell.RegWrite("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\2\\1405","0","REG_DWORD");
        WshShell.RegWrite("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\2\\2201","0","REG_DWORD");
        
        //修改IE ActiveX安全设置:3Internet区域
        WshShell.RegWrite("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\3\\1001","0","REG_DWORD");
        WshShell.RegWrite("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\3\\1004","0","REG_DWORD");
        WshShell.RegWrite("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\3\\1200","0","REG_DWORD");
        WshShell.RegWrite("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\3\\1201","0","REG_DWORD");
        WshShell.RegWrite("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\3\\1405","0","REG_DWORD");
        WshShell.RegWrite("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\3\\2201","0","REG_DWORD");
 
        //禁用Winxp弹出窗口阻止程序
        WshShell.RegWrite("HKEY_CURRENT_USER\\Software\\Microsoft\\Internet Explorer\\New Windows\\PopupMgr","no");
    }catch(e){   
         //alert("不允许ActiveX控件");   
    }   
}

3.问题
1)网页修改activex安全设置该段代码也是必须在启用ActiveX的条件下调用成功,是需要用户在Internet的配置项中设置的(如下图),如何才能自动启用该插件?

2) chrome、火狐如何通过JS设置页边距、页眉、页脚?

3) IE高版本浏览器、火狐如何通过JS弹出浏览器自己的打印预览?