精华内容
下载资源
问答
  • 大学生毕业设计项目实训-留言板系统(PC端+手机移动端+后台管理端源代码).zip
  • pc端什么意思 PC端是和移动终端相对应的名词,就是指网络世界里可以连接到电脑主机的那个端口,是基于电脑的界面体系,它有别于移动端的手机界面体系。 其实PC的英文全称是:Personal Computer 翻译成中文的意思...
  • 什么PC端

    千次阅读 2021-03-04 14:13:19
    PC端是和移动终端相对应的名词,就是指网络世bai界里可以连接到电脑主机的那个端口,是基于电脑的界面体系,它有别于移动端的手机界面体系。 其实PC的英文全称是:Personal Computer 翻译成中文的意思是:个人计算机...
       PC端是和移动终端相对应的名词,就是指网络世bai界里可以连接到电脑主机的那个端口,是基于电脑的界面体系,它有别于移动端的手机界面体系。
    其实PC的英文全称是:Personal Computer 翻译成中文的意思是:个人计算机或者个人电脑。PC是一个具有广泛含义的词语,也是电脑的统称。就目前而言个人电脑种类有很多,比如传统的台式电脑、DIY电脑、笔记本电脑、以及近年来开始流行的平板电脑、一体机电脑、超级本、掌上电脑、嵌入式计算机均属于PC的范畴。也就是说PC是一个广泛词,属于电脑的总称。
    
    
    扩展资料:
    
    	PC端与移动端区别
    	 1. 操作方式
    
    PC端的操作方式与移动端已经有了明显的差别,PC端使用鼠标操作,操作包含滑动、左击、右击、双击操作,操作相对来说单一,交互效果相对较少,而对于手机端来说,包含手指操作点击、滑动、双击、双指放大、双指缩小、五指收缩和苹果最新的3Dtouch按压力度,除了手指操作外还可以配合传感器完成摇一摇、陀悬仪感应灯操作方式,操作方式更加的丰富,通过这些丰富的操作可设计不同新颖吸引人的交互互动设计。
    
    	2. 屏幕尺寸
    
    随着时间的推移,移动端的设备屏幕逐渐增大,但是你再大也是大不过PC电脑屏幕的,这是毋庸置疑的。PC端屏幕大,所以他的视觉范围更广,可设计的地方更多,设计性更强,相对来说容错度更高一些有一些小的纰漏不容易被发现。移动端设备相对来说屏幕较小,操作局限性大,在设计上可用空间显得尤为珍贵,在小小的屏幕上使用粗大的手指操作也需要在设计中避免原件过小过近。
    
    	3. 网络环境
    
    当下不管是移动端还是PC端都离不开网络,PC端设备连接网络更加稳定,而移动端可能遇到信号问题导致网络环境不佳,出现网速差甚至断网的问题,这就需要产品经理在设计中充分考虑网络问题,更好的设计相应的解决方案。
    	4. 传感器
    
    移动端设备重磅武器来袭,完善的传感器是PC端设备望尘莫及的,压力、方向、重力、GPSNFC、指纹识别、3Dtouch、陀螺仪等等等等,就是因为这些传感器的存在才使得我们的生活更加丰富多彩,有了他们你才能玩赛车游戏才能摇妹子才能统计每天走了多少步,产品在设计中巧妙地使用传感器能让产品添姿加彩。
    	5. 使用场景与使用时间
    
    这两块我们一起来说,因为PC端设备的使用场景多为在家或者学校公司等一些固定的场景,所以其使用时间偏向于持续化,在一个特定的时间段内持续使用,而移动端设备不受局限可以吃饭用、坐车用、拉屎用、无聊打发时间用、躺着用、坐着用、倒立着用都没人管你,随时随地想用就用,所以他的使用时间更加灵活,时间更加碎片化,所以在操作上更偏向于短时间内可完成的。
    
    	6. 软件迭代时间以及更新频次
    
    你有没有很久都没有更新你的PC软件了,但是你的手机软件确实永远保持着最新的状态,这就是他们两者的区别,对于移动端他的软件迭代时间较短,用户更新率较高而PC端软件迭代时间较长,除非出于需要用户一般不会主动更新软件,软件更新率低。
    
    	7. 续航
    
    除了笔记本PC端台式机只要有点他就从没有考虑过这个问题,移动端设备则需要考虑。 
    
    参考资料:百度百科——终端
    
    展开全文
  • 记得几年前刚进入公司两个星期,第一次接触游戏SDK玩意,还在熟悉代码的过程中,产品经理开了个需求会,意思是现在和三七互娱在对接一个游戏,公司想在PC端实现多渠道打包和替换背景图(目前背景图是拉伸的,要替换...

          最近查看一下电脑资料,找到一个印象很深刻的项目。记得几年前刚进入公司两个星期,第一次接触游戏SDK玩意,还在熟悉代码的过程中,产品经理开了个需求会,意思是现在和三七互娱在对接一个游戏,公司想在PC端实现多渠道打包和替换背景图(目前背景图是拉伸的,要替换三七互娱给的背景图),就是运营人员在PC端上能操作多渠道打包。类似易接那样。我脑海里十万个为什么,什么鬼?什么东西?什么情况?这不是要C语言来实现的吗?不是要C来生成exe执行程序吗?按我的经验我实现不了,产品经理回复,我不管,只要很简单实现就可以了。   

        回到座位上脑袋一片空白,完全没有思路。那时很想放弃,但后来想想,还是尝试一下。 

        想到要解决的问题

    1. java如何在PC端可运行?
    2. 操作界面如何绘画?
    3. 如何实现替换渠道号和背景图?

        通过求助百度,大致有了思路

    1. eclipse中打包成jar包可选择可运行jar。(习惯使用Android Studio开发,eclipse使用不熟悉,没办法,回归到eclipse)   
    2. java中有个swing的界面库(java中不经常使用,几乎抛弃了) 
    3. 幸好渠道文件是放在asset中,不被编译成二进制,只要将asset文件下的渠道文件替换渠道号就可,那么整体就是解包--替换渠道号和背景图-->打包并签名。

    以下是部分实现代码,希望给遇到类似的问题的同学们提供个思路。

    绘制页面代码:

    private static final long serialVersionUID = 1L;
    
    	private JTextField apkUploadName;
    	private JButton upLoadBtn;// 上传按钮
    	private JTextField apkFilePath;// 显示上传路径
    
    	private JTextField channelName;
    	private JTextField channelField;
    	private JButton changeChannelBtn;// 更改渠道号
    
    	private JTextField appidTextField;// 修改appid
    
    	private JTextField appKeyTextField;// 修改appKey
    
    	private JTextField bgField;
    	private JButton changeBgImageBtn;// 更改背景图
    	private JTextField bgTextUrlField;
    
    	private JTextField splashText;
    	private JButton changeSplashImageBtn;// 更改背景图
    	private JTextField splashTextUrlField;
    
    	private JButton signButton;// 打包签名
    	private JProgressBar progressBar;
    	
    	private JTextField signTextUrl;// 路径
    	private JTextField signText;// 签名路径
    	
    	private JButton sureBtn;// 确认按钮
    
    	private JButton canclBtn;// 取消按钮
    
    	public static final int WIDTH = 800;
    	public static final int HEIGTH = 600;
    
    	private JTextField appid;
    	private JTextField appKey;
    	private ArrayList<String> channelkey = new ArrayList<String>();
    
    	private JPanel biggerJPanel;
    
    	/*public static void main(String[] args) {
    		ToolDemo toolDemo = new ToolDemo();
    		toolDemo.setVisible(true);
    	}*/
    
    	public ToolDemo() {
    		super("游戏母包分包工具");
    		this.setSize(WIDTH, HEIGTH);
    		this.setLocation(500, 300); // 设置窗体在屏幕的位置
    		Container contentPane = getContentPane();
    		contentPane.setBackground(Color.CYAN);
    		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);// 设置JVM退出后,窗体的退出属性
    		
    		initView();
    		initJPane();
    	}
    
    	private void initView() {
    		
    		apkUploadName=new JTextField(Constants.APKUPLOADNAME);
    		apkUploadName.setBounds(50, 50, 90, 25);
    		setStyle(apkUploadName);
    		
    		apkFilePath = new JTextField();
    		apkFilePath.setHorizontalAlignment(JTextField.LEFT);
    		apkFilePath.setBounds(150, 50, 450, 25);
    
    		upLoadBtn = new JButton(Constants.UPLOADAPK);
    		upLoadBtn.addActionListener(this);
    		upLoadBtn.setBounds(620, 50, 80, 25);
    		
    		channelName = new JTextField(Constants.CHANGECHANNEL);
    		channelName.setBounds(50, 100, 80, 25);
    		setStyle(channelName);
    
    		channelField = new JTextField();
    		channelField.setEditable(true);
    		channelField.setBounds(150, 100, 450, 25);
    
    		changeChannelBtn = new JButton(Constants.CHANGECHANNEL);
    		changeChannelBtn.addActionListener(this);
    		changeChannelBtn.setBounds(620, 100, 80, 25);
    
    		appid = new JTextField(Constants.APPID);
    		appid.setBounds(50, 150, 50, 25);
    		setStyle(appid);
    
    		appidTextField = new JTextField();
    		appidTextField.setEditable(true);
    		appidTextField.setBounds(130, 150, 100, 25);
    
    		appKey = new JTextField(Constants.APPKEY);
    		appKey.setBounds(250, 150, 60, 25);
    		setStyle(appKey);
    
    		appKeyTextField = new JTextField();
    		appKeyTextField.setEditable(true);
    		appKeyTextField.setBounds(320, 150, 200, 25);
    
    		bgField = new JTextField(Constants.UPDATEBACKGROUD);
    		bgField.setBounds(50, 200, 80, 25);
    		setStyle(bgField);
    
    		bgTextUrlField = new JTextField();
    		bgTextUrlField.setHorizontalAlignment(JTextField.LEFT);
    		bgTextUrlField.setBounds(150, 200, 450, 25);
    
    		changeBgImageBtn = new JButton(Constants.LIULAN);
    		changeBgImageBtn.addActionListener(this);
    		changeBgImageBtn.setBounds(620, 200, 80, 25);
    
    		splashText = new JTextField(Constants.UPDATESPLASH);
    		splashText.setBounds(50, 250, 80, 25);
    		setStyle(splashText);
    
    		splashTextUrlField = new JTextField();
    		splashTextUrlField.setHorizontalAlignment(JTextField.LEFT);
    		splashTextUrlField.setBounds(150, 250, 450, 25);
    
    		changeSplashImageBtn = new JButton(Constants.LIULANIMAGE);
    		changeSplashImageBtn.addActionListener(this);
    		changeSplashImageBtn.setBounds(620, 250, 80, 25);
    
    		signText = new JTextField(Constants.SIGNURL);
    		signText.setBounds(50, 300, 80, 25);
    		setStyle(signText);
    
    		signTextUrl = new JTextField();
    		signTextUrl.setHorizontalAlignment(JTextField.LEFT);
    		signTextUrl.setBounds(150, 300, 450, 25);
    
    		signButton = new JButton(Constants.CHOOSE);
    		signButton.addActionListener(this);
    		signButton.setBounds(620, 300, 80, 25);
    		
    		progressBar=new JProgressBar();
    		progressBar.setBounds(150, 310, 450, 30);
    	    progressBar.setMinimum(0);
    	    progressBar.setMaximum(100);
    	    progressBar.setStringPainted(true);
    	    progressBar.setBorderPainted(true);
            progressBar.setUI(new MetalProgressBarUI());
            progressBar.setBackground(Color.CYAN);
            progressBar.setForeground(Color.BLUE);
    	    
    	    
    		sureBtn = new JButton(Constants.SURE);
    		sureBtn.addActionListener(this);
    		sureBtn.setBounds(200, 400, 100, 25);
    
    		canclBtn = new JButton(Constants.CANCLE);
    		canclBtn.addActionListener(this);
    		canclBtn.setBounds(400, 400, 100, 25);
    	}
    
    	private void initJPane() {
    		biggerJPanel = new JPanel();
    		biggerJPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
    		//biggerJPanel.setBackground(new Color(0, 0, 0,1));
    		setContentPane(biggerJPanel);
    		biggerJPanel.setLayout(null);
    
    		biggerJPanel.add(apkUploadName);
    		biggerJPanel.add(apkFilePath);
    		biggerJPanel.add(upLoadBtn);
    		biggerJPanel.add(changeChannelBtn);
    		biggerJPanel.add(channelField);
    		biggerJPanel.add(channelName);
    		biggerJPanel.add(appidTextField);
    		biggerJPanel.add(appKeyTextField);
    		biggerJPanel.add(appid);
    		biggerJPanel.add(appKey);
    		biggerJPanel.add(bgField);
    		biggerJPanel.add(bgTextUrlField);
    		biggerJPanel.add(changeBgImageBtn);
    		biggerJPanel.add(splashText);
    		biggerJPanel.add(changeSplashImageBtn);
    		biggerJPanel.add(splashTextUrlField);
    		/*biggerJPanel.add(signButton);
    		biggerJPanel.add(signText);
    		biggerJPanel.add(signTextUrl);*/
    		
    		//biggerJPanel.add(progressBar);
    		biggerJPanel.add(sureBtn);
    		biggerJPanel.add(canclBtn);
    	}
    
    	private void setStyle(JTextField text) {
    		text.setBorder(null);
    		text.setHorizontalAlignment(JTextField.LEFT);
    		text.setFont(new Font("楷体", Font.PLAIN, 16));
    		text.setEditable(false);
    	}

     解包:

    // 解压
    	@SuppressWarnings("rawtypes")
    	public static void unZip(String fileName, String filePath) throws Exception {
    		ZipFile zipFile = new ZipFile(fileName);
    		Enumeration emu = zipFile.entries();
    
    		while (emu.hasMoreElements()) {
    			ZipEntry entry = (ZipEntry) emu.nextElement();
    			if (entry.isDirectory()) {
    				new File(filePath + entry.getName()).mkdirs();
    				continue;
    			}
    			BufferedInputStream bis = new BufferedInputStream(
    					zipFile.getInputStream(entry));
    
    			File file = new File(filePath + entry.getName());
    			File parent = file.getParentFile();
    			if (parent != null && (!parent.exists())) {
    				parent.mkdirs();
    			}
    			FileOutputStream fos = new FileOutputStream(file);
    			BufferedOutputStream bos = new BufferedOutputStream(fos, BUFFER);
    
    			byte[] buf = new byte[BUFFER];
    			int len = 0;
    			while ((len = bis.read(buf, 0, BUFFER)) != -1) {
    				fos.write(buf, 0, len);
    			}
    			bos.flush();
    			bos.close();
    			bis.close();
    		}
    		zipFile.close();
    	}

    读取文件和修改文件

    // 读取渠道文件
    	public static void setChannelFile(String txtPath,ArrayList<String> channelkey) {
    		File f = new File(txtPath);
    		if (f.exists() && f.isFile()) {
    			try {
    				BufferedReader br = new BufferedReader(new FileReader(f));
    				String line = null;
    				while ((line = br.readLine()) != null) {
    					channelkey.add(line.trim());
    				}
    				System.out.println(channelkey.toString());
    			} catch (Exception e) {
    				e.printStackTrace();
    				JOptionPane.showMessageDialog(null, "渠道文件有误", "错误", JOptionPane.ERROR_MESSAGE);
    			}
    		}
    	}
    
    
    	//读取、修改、写出txt文件
    	public static void updateChannelkey(String path, String key)throws Exception {
    		BufferedReader br = new BufferedReader(new FileReader(path));
    		String lineKey = null;
    		StringBuffer sb = new StringBuffer();
    		while ((lineKey = br.readLine()) != null) {
    			System.out.println(lineKey);
    			lineKey = lineKey.replaceAll(lineKey.trim(), key);
    			System.out.println(lineKey);
    			sb.append(lineKey + "\n");
    		}
    		br.close();
    
    		FileWriter fw = new FileWriter(path);
    		fw.write(sb.toString());
    		fw.close();
    	}

    最后打包和签名

    //打包及签名
    	public static void compressAndSignApk(StringBuffer buffer, String signPath,
    			String apkSrcPath, String apkName, String prefixName,
    			String targetPath, String resultPath, String key) throws Exception {
    		// 判断创建文件夹
    		File targetFile = new File(targetPath);
    		if (!targetFile.exists()) {
    			targetFile.mkdir();
    		}
    
            //打包
    		ZipUtils.compress(apkSrcPath+ Constants.SOURE_PATH_NAME + prefixName,targetPath + apkName);
    
    		// 判断创建文件夹
    		File resultFile = new File(resultPath);
    		if (!resultFile.exists()) {
    			resultFile.mkdir();
    		}
    
    		// 组合签名命令
    		String apkSign = apkName.split(".apk")[0] + "_signed_"+ key + ".apk";
    		buffer.setLength(0);
    		buffer.append("cmd.exe /c jarsigner -digestalg SHA1 -sigalg MD5withRSA -tsa https://timestamp.geotrust.com/tsa -keystore ")
    			.append(signPath).append(" -storepass ")
    			.append(Constants.SIGN_PASSWORD)
    			.append(" -signedjar ").append(resultPath)
    			.append(apkSign).append(" ") // 签名保存路径应用名称
    			.append(targetPath).append(apkName).append(" ") // 打包保存路径应用名称
    			.append(Constants.SIGN_NAME);
    		System.out.println(buffer.toString());
    		if (buffer.toString()!=null) {
    			CommanUtils.runCmd(buffer.toString());
    		}else {
    			JOptionPane.showMessageDialog(null, "签名有误", "错误", JOptionPane.ERROR_MESSAGE);
    		}
    	}
    
    // 执行cmd命令
    	public static void runCmd(String cmd) {
    		Runtime rt = Runtime.getRuntime();
    		try {
    			Process p = rt.exec(cmd,null);
    			// p.waitFor();
    			BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
    				String msg = null;
    				while ((msg = br.readLine()) != null) {
    					System.out.println(msg);
    				}
    			/*if(p.waitFor()!=0){
    				JOptionPane.showInputDialog("打包失败!");
    			}*/
    		} catch (Exception e) {
    			e.printStackTrace();
    			JOptionPane.showMessageDialog(null, "cmd命令运行错误", "错误", JOptionPane.ERROR_MESSAGE);
    		}
    	}
    

    最后说一下,用了SwingSets2(BeautyEyeLNFDemo).jar实现外观精致。实测打包50个,大概用了15分钟(系甘上下)。我不是专科出生的,没多大经验,能做出这样的一个需求,自己也觉得不可思议,但最终产品没用这个工具。希望这样的实现思路能给遇到类似的问题的伙伴们提供思路。

    展开全文
  • Django pc app微信登录

    2020-09-27 09:48:42
    最近项目中需要微信登录,不仅要pc端登录,还要有app端的登录,今天,先记录一下pc端微信登录,首先我查看了微信登录的官网,里面写了好多,但是到最后总结,其实说了好多废话,好多步骤都是用不要的,其实只是需要...

    最近项目中需要微信登录,不仅要pc端登录,还要有app端的登录,今天,先记录一下pc端微信登录,首先我查看了微信登录的官网,里面写了好多,但是到最后总结,其实说了好多废话,好多步骤都是用不要的,其实只是需要两步就可以了:

    1. 向微信请求url,什么意思哪,就是后台需要请求一个链接,拿到链接之后,发送给前端,前端拿到这个url之后,发送请求,这样就会得到一个一个二维码,用户会可以扫这个二维码进行登录
    class WeChatAuthURLView(APIView):
        """获取微信登录url(获取code)"""
    
        def get(self, request):
            # 先获取查询字符串中redirect url的值
            # next = request.query_params.get('redirect')
            oauth = OauthWeChat()
            # 获取微信code的url
            login_url = oauth.get_code_url()
            return APIResponse.success(data={'login_url': login_url}, message='OK')
    
    import requests
    import json
    import random
    from urllib.parse import urlencode
    from itsdangerous import TimedJSONWebSignatureSerializer as TJWSSerializer, BadData
    from django.conf import settings
    
    from oauth import constents
    
    class OauthWeChat(object):
        """微信登录工具"""
    
    
        def get_code_url(self):
            """
            获取微信登录的url
            返回说明:redirect_uri?code=CODE&state=STATE;
            请求成功返回code和state,否则只有state
            """
    
            redirect_uri = 'http://www.xxxxx.com/mall/perfect'
            url = 'https://open.weixin.qq.com/connect/qrconnect?'
            params = {
                'appid' : settings.WE_CHAT_APP_ID,
                'redirect_uri' : redirect_uri,
                'response_type' : 'code',
                'scope' : 'snsapi_login',
                'state' : self.generate_state(),
            }
    
            # resp = requests.get(url, params =params)
            params = urlencode(params)
            url = url + params
            return url
       
    
        def generate_state(self):
            """生成state"""
    
            serializer = TJWSSerializer(settings.SECRET_KEY, expires_in=constents.SAVE_WECHAT_USER_TOKEN_EXPIRES)
            num = random.randint(1, 999)
            state = serializer.dumps({'num': num}).decode()
            return state
    

    至于请求url时,携带的参数微信文档上就有,我就不再说明了,只说一下这个参数:redirect_uri = ‘http://www.xxxx.com/mall/perfect’, 这个是什么哪,这个参数其实是前端的一个页面的地址,当用户扫码之后,用户授权登录,这时候微信就会重定向到这个页面,并且带上code和state,如’http://www.xxxx.com/mall/perfect?code=CODE&state=STATE,这时候,前端拿到code和state请求后端接口,后端拿到之后,验证state,防止csrf攻击,验证成功之后,拿到code,请求appid(其实access_token我们不需要)
    2. 前端凭借code和state来访问后端,后端凭借code去向微信拿appid,拿到appid之后,去表里面查有这个appid没有,如果没有,说明用户有两种情况1.该用户注册了账号,但是这是第一次用微信登录2.该用户从来没有登录,还没有账号,不管是哪一种情况,我们直接将oppid加密返回给前端,这时候,页面redirect_uri = 'http://www.onefashionline.com/mall/perfect’就又有作用了,页面里面就让用户填写用户账号,填写之后,将oppid和用户信息一起请求后端接口,后端通过用户信息的手机号(区分用户)来查询用户注册过账号没有,注册过则将用户信息和oppid关联起来,如果没有,将用户注册并与oppid关联,第二次微信登录时,查询oppid,就能查到,这样直接办法token,状态保持即可

        def check_state(state):
            """
            检验保存用户数据的state
            :param num: num
            :return: num or None
            """
            serializer = TJWSSerializer(settings.SECRET_KEY, constents.SAVE_WECHAT_USER_TOKEN_EXPIRES)
            try:
                data = serializer.loads(state)
            except BadData:
                return None
            else:
                return data.get('num')
    
    
        def generate_bind_user_access_token(self, openid):
            """通过openid生成保存用户数据的token"""
    
            # 通过itsdangerous生成凭据access_token
            serializer = TJWSSerializer(settings.SECRET_KEY, expires_in=constents.SAVE_WECHAT_USER_TOKEN_EXPIRES)
    
            # serializer.dumps(数据), 返回bytes类型
            token = serializer.dumps({'openid': openid}).decode()
    
            return token
    
        @staticmethod
        def check_save_user_token(token):
            """
            检验保存用户数据的token
            :param token: token
            :return: openid or None
            """
            serializer = TJWSSerializer(settings.SECRET_KEY, constents.SAVE_WECHAT_USER_TOKEN_EXPIRES)
            try:
                data = serializer.loads(token)
            except BadData:
                return None
            else:
                return data.get('openid')
    
    class WeChatAuthUserView(CreateAPIView):
        """微信登录的用户"""
    
        # 指定序列化器,参数校验和用户创建在序列化器中完成
        serializer_class = OAuthWeChatUserSerializer
    
        def get(self, request):
            # 获取code
            code = request.query_params.get('code')
            state = request.query_params.get('state','')
    
            # app微信登录需要携带参数type
            type = request.query_params.get('type', None)
            if type and type == 'app':
                if not code:
                    return APIResponse.fail(message='登录失败,请重试')
                # 获取openid access_token等参数
                result = AppOauthWeChat().get_access_token(code)
                if result:
                    openid = result.get('openid')
                else:
                    return APIResponse.fail(message="微信服务器异常")
                # 根据openID判断用户是否是第一次登陆
                wechat_user = OAuthWeChatUser.objects.filter(openid=openid).first()
    
                # 如果用户不存在就是第一次登陆,通过openid生成access_token返回,用来标记用户身份
                if not wechat_user:
                    # 此处使用pc端的加密,因为校验在序列化器中校验,使用的是pc端的,要保持一致
                    token = OauthWeChat().generate_bind_user_access_token(openid)
                    data = {"access_token": token}
                    return Response({'code': 301, 'data': data, 'message': 'OK'})
    
                # 如果不是,签发JWTtoken,保存用户状态
                # 获取user对象
                user = wechat_user.user
                jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
                jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
                payload = jwt_payload_handler(user)
                token = jwt_encode_handler(payload)
    
                # 更改登录时间
                now_time = datetime.datetime.now()
                User.objects.filter(id=user.id).update(last_login=now_time)
    
                response = {
                    'token': token,
                    'user_id': user.id,
                    'role': user.role,
                    'username': user.username
                }
                return APIResponse.success(data=response, message='OK')
            
            # pc端登录
            oauth = OauthWeChat()
            if not oauth.check_state(state):
                return APIResponse.fail(message='错误的请求')
    
            if not code:
                return APIResponse(message="登录失败,请重试")
            # 根据code获取openID,  可以在工具类中定义获取openID的方法
    
            # access_token, openid = oauth.get_access_token(code)
            result = oauth.get_access_token(code)
            if result:
                # access_token = result.get('access_token')
                openid = result.get('openid')
            else:
                return APIResponse.fail(message="微信服务器异常")
    
    
            # 根据openID判断用户是否是第一次登陆
            wechat_user = OAuthWeChatUser.objects.filter(openid=openid).first()
    
            # 如果用户不存在就是第一次登陆,通过openid生成access_token返回,用来标记用户身份
            if not wechat_user:
                token = oauth.generate_bind_user_access_token(openid)
                # 添加用户信息
                # return APIResponse.success(data={"access_token": token},message='OK')
                data = {"access_token": token}
                return Response({'code':301,'data':data,'message':'OK'})
    
            # 如果不是,签发JWTtoken,保存用户状态
            # 获取user对象
            user = wechat_user.user
            jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
            jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
            payload = jwt_payload_handler(user)
            token = jwt_encode_handler(payload)
    
            # 更改登录时间
            now_time = datetime.datetime.now()
            User.objects.filter(id=user.id).update(last_login=now_time)
    
            response = {
                'token': token,
                'user_id': user.id,
                'role':user.role,
                'username': user.username
            }
            return APIResponse.success(data=response,message='OK')
    
    
        @transaction.atomic
        def create(self, request, *args, **kwargs):
            """绑定微信用户"""
    
            serializer = self.get_serializer(data=request.data)
            if not serializer.is_valid():
                message = ','.join(
                    serializer.errors[key] for key in serializer.errors if isinstance(serializer.errors[key], str))
                if not message:
                    message = ','.join(
                        serializer.errors[key][0] for key in serializer.errors if isinstance(serializer.errors[key], list))
                return APIResponse.fail(message=message)
    
            data = serializer.validated_data
            mobile = data['mobile']
            openid = data['openid']
            user = User.objects.filter(mobile=mobile).first()
    
            if not user:
                username = '用户_' + mobile[-4:]
                user = User.objects.create_user(username=username, mobile= mobile, password=data['password'],role=1)
                share_url_token = user.generate_token()
                UserInfo.objects.create(user=user, auth_state=0, share_url_token=share_url_token)
    
                # 添加用户注册IP归属地
                x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    
                if x_forwarded_for:
                    ip = x_forwarded_for.split(',')[0]  # 这里是真实的ip
                else:
                    ip = request.META.get('REMOTE_ADDR')  # 这里获得代理ip
    
                # 注册时根据ip来查询所在地(此时类型先写死为web)
                ip_home(user.id, ip, 1)
    
            else:
                user.password = make_password(data['password'])
                user.save()
    
            OAuthWeChatUser.objects.create(user=user, openid = openid)
            # 签发jwt token
            jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
            jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
    
            payload = jwt_payload_handler(user)
            token = jwt_encode_handler(payload)
    
            # 更改登录时间
            now_time = datetime.datetime.now()
            User.objects.filter(id=user.id).update(last_login=now_time)
    
            response = {
                'token': token,
                'user_id': user.id,
                'role': user.role,
                'username': user.username
            }
            return APIResponse.success(data=response, message='OK')
    
    1. 可以看到,这里面还有app登录,app登录和pc端登录不同的时,第一步的操作,就是请求code不需要后端操作,这里app前端会唤醒微信,直接拿到code,然后带上code直接就从第二步开始了
      4.微信开放平台网址:https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html
    展开全文
  • 当你想要内容大小随着屏幕大小自动适应的时候就可以使用bootstrap,也就是在pc端以及不同手机(显示屏大小不同)端内容也能够正常显示的时候。 一行最多占十二个标签,不管是大屏还是超小屏的时候。 col-lg一般用于...

    当你想要内容大小随着屏幕大小自动适应的时候就可以使用bootstrap,也就是在pc端以及不同手机(显示屏大小不同)端内容也能够正常显示的时候。
    一行最多占十二个标签,不管是大屏还是超小屏的时候。

    col-lg一般用于大屏设备,
    (min-width:1200px);

    col-md一般用于中屏设备,
    (min-width:992px);

    col-sm一般用于小屏设备,
    (min-width:768px);

    col-xs用于超小型设备,
    (max-width:768px);

    后面跟数字是几,也就是占几份(每个占据12份中的几份),
    比如是4,也就是一行可以显示3个;
    或者12,就是一行可以显示1个。

    关于使用,一般设置的话四个属性都用到会比较好,这样就可以在不同屏幕上很好的展示。
    比如你有了12个section标签,你想让他们在不同屏幕大小的时候有不同的展示方式,大屏时一行显示6个,中屏时一行显示3个,小屏时一行展示2个,超小屏一行展示1个,你就可以在每一个section标签里面这样写:

    <section class = “col-lg-2 col-md-4 col-sm-6 col-xs-12”></section>
    

    HTML代码:

      <a-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12"> </a-col>
    

    当屏幕尺寸

    小于 768px 的时候,用 col-xs-12 类对应的样式;

    在 768px 到 992px 之间的时候,用 col-sm-9 类对应的样式;

    在 992px 到 1200px 之间的时候,用 col-md-6 类对应的样式;

    大于 1200px 的时候,用 col-lg-3 类对应的样式;

    展开全文
  • 由于 TCP 协议的限制,PC 只有65536个端口可用以向外部发出连接,而操作系统对半开连接数也有限制以保护操作系统的 TCP\IP 协议栈资源不被迅速耗尽,因此浏览器不好发出太多的 TCP 连接,而是采取用完了之后再重复...
  • PC端的模拟器也好,手机端的伪装软件也罢,在“本地购物环境”这一个环节,其核心的任务就是要把本地的信息给“伪装”起来。亚马逊会对本地设备(包括浏览器)进行关联,模拟器或伪装软件就制造出100个、甚至上千个...
  • 在ecshop中,有很多它自己封装好的类和方法,其中就有这一个,是在我在找pc端商品页面评价展示,我在html页面找,结果只有 {insert name='comments' type=$type id=$id} 一行代码后来,经过一番努力,其实是找到了一...
  • 前后分离文章

    2019-04-02 10:35:24
    1.从 MVC 到前后分离http://www.importnew.com/21589.html ...2.前端工程师你真的懂前后分离是什么意思吗?https://baijiahao.baidu.com/s?id=1561111462074628&wfr=spider&for=pc 3.http://blo...
  • 谷歌在站长世界(webmaster)在举办的2020 PubCon大会上表示:“从明年2021年3月份起,对只有PC页面的站点网页内容将被忽略,意思是如果你的站点只有PC端,没有移动端,那么你的网站将不会再被谷歌搜索引擎收录,...
  • 这个feature应该不仅仅只关心手机,而且还包括PC,因为苹果不仅仅在手机(从iphone4开始),而且在,MAC上也使用了retina.首先,retina的意思就是,dpr(device-pixel-ratio)是普通屏幕的两倍.对比于CSS来说就是,原来在...
  • 1、Web前端是什么意思 Web前端是网站前台部分,运行在PC端,移动端等浏览器上展现给用户所浏览的网页。 用我们的话来说,前端就是网页给访问网站的人看的内容和页面,Web前端开发意思就是这些内容的制作,也就是代码...
  • 大家好我是微风,一个爱设计爱生活的平面设计师,最近很多朋友都在问什么是UI设计?零基础能学习UI设计吗?...UI设计分类:移动端UI设计,PC端UI设计,游戏端UI设计,其它端UI设计。 好的UI设计不仅
  • 很多学生问我前端是到底是什么?...:就是终端的意思,也就是客户端的一些载体,比如手机,电脑等。合起来,前端:就是终端的的表现。放在PC(电脑)上,或手机上,就是呈现在我们眼前的页面样式和动画(...
  • HTML5是什么

    2021-04-16 10:57:14
    HTML可以理解为一门程序语言,HTML5字面的...相比较之前版本,最大的变动就是除了对PC端个浏览器解析起来更加方便快捷外,更加适合移动端的Web开发,因此增加了很多标签和属性,比如<article>、<nav>、<
  • Web前端开发人才在互联网企业中越来越吃香,因此成为不少人转行的首选。但随着互联网技术的进步,Web前端领域划分...经过了这个阶段过后你就需要开始JavaScript和PC端全栈的学习了,通过这个阶段实战完整的前端工程
  • 首先我们来理解一下pc端什么可以看到网站上设置的微软雅黑字体:微软在2006年12月发布微软雅黑随简体中文版Windows Vista一起发布,是Windows Vista默认字体。意思就是window7以上的微软系统都有默认的微软雅黑...
  • 移动端 H5 --页面适配(二)

    万次阅读 多人点赞 2018-08-15 10:14:29
    在了解如何做H5页面适配前,大家都应该把移动端涉及的一些概念搞明白,比如:dpr 是什么意思? 移动端H5解惑-概念术语(一) 二、为什么要做页面适配 2.1 PC端为什么要解决浏览器兼容 因为在PC端,由于...
  • 移动端H5解惑-页面适配(二)

    千次阅读 2018-08-04 01:41:45
    在了解如何做H5页面适配前,大家都应该把移动端涉及的一些概念搞明白,比如:dpr 是什么意思? 移动端H5解惑-概念术语(一) 二、为什么要做页面适配 2.1 PC端为什么要解决浏览器兼容 因为在PC端,由于浏览器种...
  • 移动端 H5页面适配

    2019-02-28 17:30:58
    在了解如何做H5页面适配前,大家都应该把移动端涉及的一些概念搞明白,比如:dpr 是什么意思? 移动端H5解惑-概念术语(一) 二、为什么要做页面适配 2.1 PC端为什么要解决浏览器兼容 因为在PC端,由于浏览器...
  • 目录 手机APP抓包工具 如何抓包手机APP包 ...Charles抓包看到unknown是什么意思 手机APP抓包工具 1、fiddler 【推荐PC电脑使用】 2、Charles【推荐PC、Mac使用】 3、HttpAnalyzerStdV7 4.
  • 响应式布局是什么意思? 响应式布局可以根据不同的浏览设备(PC端,平板,智能手机等)呈现不同的网页布局,同时减少缩放、平移和滚动。 响应式网页设计就是一个网站能够兼容多个终端而不是为每个终端做一个特定的...
  • 1. 渐进增强和优雅降级分别是什么意思? 2. 什么是 CSS hack?在哪个网站查看标签(属性)的浏览器兼容情况? 3. IE6、7 的 hack 写法是? 4. 尽可能多的列举浏览器兼容的处理范例? 5. css reset 是什么?css 预...
  • 移动端GPGPU 架构

    2021-05-10 10:24:44
    最近在面试的时候发现移动端现在是越来越热,然后就有被问到GPU的框架什么PC端的这个可以参考这个:GPU硬件架构及其运行机制移动端的与PC端有很大的区别!比如移动端可以说没有独立的显存只有些寄存器cache 和on-...
  • pc端访问无问题,移动端手机连接局域网进行访问报错 Request aborted 解决方案: devServer: { disableHostCheck: true, } 在vue项目配置文件中添加 disableHostCheck: true, 这段代码 用这个方法我解决了问题,...
  • 响应式布局

    2020-11-03 16:07:04
    所谓响应式布局,就是指同一个网页,在不同的终端上的显示效果不同,但是访问的确实是同一个页面,只是因为浏览器会根据终端的不同(例如屏幕宽度、横竖屏、移动端还是pc端等)选择的渲染方式也不同。 二、如何实现...
  •  以前的招聘,因为公司的产品线是PC端网络业务的一部分,所以对SEO(搜索引擎优化)有一定的要求。但很少有候选人能回答。  部分应聘者过去的工作经验是基于微信的后台管理系统和网络应用。偶尔,他们会遇到一个...

空空如也

空空如也

1 2 3 4
收藏数 71
精华内容 28
关键字:

pc端什么意思