首页
归档
留言
友链
广告合作
壁纸
更多
美女主播
Search
1
博瑞GE车机升级/降级
5,649 阅读
2
Mac打印机设置黑白打印
5,043 阅读
3
修改elementUI中el-table树形结构图标
4,946 阅读
4
Mac客户端添加腾讯企业邮箱方法
4,705 阅读
5
intelliJ Idea 2022.2.X破解
4,459 阅读
后端开发
HarmonyOS Next
Web前端
微信开发
开发辅助
App开发
数据库
随笔日记
登录
/
注册
Search
标签搜索
Spring Boot
Java
Vue
Mac
Spring Cloud
MyBatis
WordPress
MacOS
asp.net
Element UI
Nacos
MySQL
.Net
Spring Cloud Alibaba
Mybatis-Plus
Typecho
jQuery
Java Script
IntelliJ IDEA
微信小程序
Laughing
累计撰写
629
篇文章
累计收到
1,421
条评论
首页
栏目
后端开发
HarmonyOS Next
Web前端
微信开发
开发辅助
App开发
数据库
随笔日记
页面
归档
留言
友链
广告合作
壁纸
美女主播
搜索到
629
篇与
的结果
2021-01-04
Vue+element-ui导出el-table中的数据
1.先安装依赖npm install --save xlsx file-saver2.在要导出的vue组件中的script引入import FileSaver from "file-saver" import XLSX from "xlsx"3.导出方法exportExcel() {//执行此方法导出Excel表格 // 为el-table添加一个id:out-table // 当el-table使用了fixed时会导出两次数据,所以要先进行判断 var fix = document.querySelector('.el-table__fixed'); var wb; if (fix) { // 如果有fixed,先移除,然后再添加上 wb = XLSX.utils.table_to_book(document.querySelector("#out-table").removeChild(fix)) document.querySelector("#out-table").appendChild(fix) }else{ wb = XLSX.utils.table_to_book(document.querySelector("#out-table")) } var wbout = XLSX.write(wb, { bookType: "xlsx", bookSST: true, type: "array" }); try { FileSaver.saveAs( new Blob([wbout], { type: "application/octet-stream" }), // 导出的文件名称 "Data.xlsx" ) } catch (e) { if (typeof console !== "undefined") console.log(e, wbout); } return wbout; },这个方法也存在问题,比如样式不够灵活等。
2021年01月04日
1,705 阅读
0 评论
0 点赞
2021-01-04
el-datepicker设置可选日期范围
1.只能选择当前及以后的日期<el-date-picker v-model="value1" type="date" :picker-options="pickerOptions"> </el-date-picker> data() { return { pickerOptions: { disabledDate(time) { return time.getTime() < Date.now() - 8.64e7; } }, }2.只能选择今天以及今天以前的日期data (){ return { pickerOptions: { disabledDate(time) { return time.getTime() > Date.now() - 8.64e6 } }, } }3.只能选择今天之后的日期data (){ return { pickerOptions: { disabledDate(time) { return time.getTime() < Date.now(); } }, } }4.只能选择今天之前的日期data (){ return { pickerOptions0: { disabledDate(time) { return time.getTime() > Date.now(); } }, } }5.设置选择三个月之前到今天的日期data (){ return { pickerOptions0: { disabledDate(time) { let curDate = (new Date()).getTime(); let three = 90 * 24 * 3600 * 1000; let threeMonths = curDate - three; return time.getTime() > Date.now() || time.getTime() < threeMonths;; } }, } }组件代码<el-date-picker v-model="value1" type="date" placeholder="开始日期" :picker-options="pickerOptions0"> </el-date-picker> <el-date-picker v-model="value2" type="date" placeholder="结束日期" :picker-options="pickerOptions1"> </el-date-picker>
2021年01月04日
1,665 阅读
0 评论
2 点赞
2021-01-04
elemetui el-table 表头与列不对齐解决方法
最近在做项目的过程中遇到一个问题, 改变浏览器的大小, 发现 elmentui 中的 el-table 表头与 表身列不对齐。其实很简单: 只需要 当前页面添加如下 css 样式即可解决问题!.el-table th { display: table-cell !important; }
2021年01月04日
1,295 阅读
0 评论
0 点赞
2020-12-30
安装vs code服务器版
权当尝鲜吧,目前没发现有特别大的用途。一、安装下载压缩包wget https://github.com/cdr/code-server/releases/download/v3.8.0/code-server-3.8.0-linux-amd64.tar.gz解压tar -xvzf code-server-3.8.0-linux-amd64.tar.gz二、运行直接运行进入解压后的文件夹,执行以下命令./code-server默认监听端口是8080,并且只能本地运行指定密码、端口为了能够远程运行,我们可以执行ip、端口、密码等信息。依次执行以下命令export PASSWORD="你的密码"./code-server --port 9999 --host 0.0.0.0 --auth password三、后台运行如果想后台运行,可以单独打开一个窗口screen -S 窗口名称然后再打开的窗口执行以上命令即可。四、测试浏览器打开IP:端口即可运行
2020年12月30日
1,361 阅读
0 评论
3 点赞
2020-12-28
FloatingDragButton:炫酷的拖拽浮动按钮
IOS的Assistive Touch效果很炫酷,可以任意拖拽,同时点击后会展开菜单栏。然而,这不只是IOS的特权,Android也可以实现。但是由于悬浮窗需要申请权限,所以本文仅在app内实现,可以任意拖拽,并可以响应点击事件。一、效果图效果还是不错的。上图看出虽然没有像IOS一样弹出菜单栏,仅仅以Toast和旋转动画的效果代替了(因为太懒了,更炫酷的效果交给你们的想象了)。但是确实支持点击事件,并且和拖拽事件不冲突。Github地址:FloatingDragButton二、实现原理1、拖拽实现很简单,设置TouchListener监听,实现onTouch方法,在ACTION_MOVE的过程中随着x,y坐标的移动更新浮动按钮的位置。下面具体介绍重写onTouch方法的具体实现。监听ACTION_DOWN事件case MotionEvent.ACTION_DOWN:{ mDownPointerId = MotionEventCompat.getPointerId(event, 0); mPreviousX = event.getRawX(); mPreviousY = event.getRawY(); break; }记录初始的坐标以及触摸点。监听ACTION_MOVE事件case MotionEvent.ACTION_MOVE:{ if (mDownPointerId >= 0) { int index = MotionEventCompat.getActionIndex(event); int id = MotionEventCompat.getPointerId(event, index); if (id == mDownPointerId) { boolean update = adjustMarginParams(view, event); if (!update) { break; } mFloatView.requestLayout(); mHasMoved = true; result = true; } } break; }其中最重要的是adjustMarginParams(view, event)方法,来更新浮动按钮的相对位置。private boolean adjustMarginParams(View v, MotionEvent event) { float x = event.getRawX(); float y = event.getRawY(); float deltaX = x - mPreviousX; float deltaY = y - mPreviousY; if (!mHasMoved) { if (Math.abs(deltaX) < mTouchSlop && Math.abs(deltaY) < mTouchSlop) { return false; } } //左上角位置 int newX = (int)x - mFloatView.getWidth() / 2; int newY = (int)y - mFloatView.getHeight() / 2; newX = Math.max(newX, mBoundsInScreen.left + mEdgePaddingLeft); newX = Math.min(newX, mBoundsInScreen.right - mEdgePaddingRight - mFloatView.getWidth()); newY = Math.max(newY, mBoundsInScreen.top + mEdgePaddingTop); newY = Math.min(newY, mBoundsInScreen.bottom - mEdgePaddingBottom - mFloatView.getHeight()); mFloatViewWindowParam.x = newX; mFloatViewWindowParam.y = newY - mParentMarginTop; return true; }其中mBoundsInScreen代表浮动按钮可移动的矩形范围。根据当前event内的坐标与mBoundsInScreen范围比较,选择最终拖拽到达的位置,设置给浮动按钮的布局参数mFloatViewWindowParam,然后调用requestLayout更新布局。监听ACTION_UP/ACTION_CANCELcase MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL:{ if (mDownPointerId >= 0 && mHasMoved) { event.setAction(MotionEvent.ACTION_CANCEL); adjustMarginParams(view, event); mFloatView.requestLayout(); int center = (mBoundsInScreen.width() - mFloatView.getWidth()) / 2; int x = mFloatViewWindowParam.x; int destX = 0; int posX = Gravity.LEFT; //抬起时 根据位置强制把浮动按钮归于左边或右边 if (x < center) { // 左边 destX = mBoundsInScreen.left + mEdgePaddingLeft; } else { posX = Gravity.RIGHT; destX = mBoundsInScreen.right - mEdgePaddingRight - mFloatView.getWidth(); } if (mFloatButtonCallback != null) { float posY = 0; if (mBoundsInScreen.height() - mFloatView.getHeight() != 0) { posY = 1f * (mFloatViewWindowParam.y - mBoundsInScreen.top) / (mBoundsInScreen.height() - mFloatView.getHeight()); } mFloatButtonCallback.onPositionChanged(destX, mFloatViewWindowParam.y, posX, posY); } int deltaHorizon = destX - x; //小于100直接移动 否则开启动画 if (Math.abs(deltaHorizon) < 100) { mFloatViewWindowParam.x = destX; mFloatView.requestLayout(); } else { ValueAnimator animator = ValueAnimator.ofInt(x, destX); animator.setInterpolator(mInterpolator); if (mUpdateListener == null) { mUpdateListener = new FloatAnimatorUpdateListener(); mUpdateListener.setUpdateView(FloatTouchListener.this); } animator.addUpdateListener(mUpdateListener); animator.setDuration(200); animator.start(); } } resetStatus(); break; } }实现当抬起的瞬间,根据当前所处坐标靠左还是靠右,把浮动按钮置于左边缘或者右边缘。同时,调用回调,把移动相对位置传给回调函数,实现拖拽监听。当从当前位置移动到左/右边缘的距离小于100时,直接移动,否则实现动画减速移动效果。如此简单便可实现任意拖拽的效果了,具体一些细节要细看源码实现。2.点击实现也许有人会认为点击事件很好实现啊,setOnClickListener()设置个监听就可以实现了。不信你去试试,没用。其实点击实现才是本篇文章的精髓,因为灵活应用到了事件分发机制。从事件分发机制中我们知道,就优先级而言:onTouchListener>onClickListenr。上面的拖拽事件已经消费了onTouchListener(即onTouch方法中返回true),那么就不会下发到onClickListenr,自然就不会产生点击事件。也许你想让onTouchListener不消费,然后不就下发到onClickListenr了么?确实这样可以实现点击事件,但是拖拽功能又实现不了了。因为onTouch方法中返回false,确实onClickListenr接收到了事件,然后消费掉。可是因为onTouch方法中返回false,所以接下来的一切事件不能接受,没办法响应拖拽效果了。通过上面的分析,最终的解决办法就是:onTouch方法中,在接收到ACTION_DOWN后,返回false,交给onClickListenr处理。剩下的ACTION_MOVE/ACTION_UP等事件,返回true,交给onTouchListener处理,这样自然就可以既实现拖拽效果又实现点击效果了。具体实现以下面伪代码为例 public boolean onTouch(View view, MotionEvent event) { int action = MotionEventCompat.getActionMasked(event); if (mFloatButtonCallback != null) { mFloatButtonCallback.onTouch(); } boolean result = false; switch (action) { case MotionEvent.ACTION_DOWN:{ .................................................... break; } case MotionEvent.ACTION_MOVE:{ .................................................... result = true; break; } case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL:{ ................................................ break; } } return result; }原理就是这么简单,更加炫酷的效果可自定义实现,喜欢就点个star支持下吧!Github地址:https://github.com/LRH1993/FloatingDragButton
2020年12月28日
1,528 阅读
0 评论
6 点赞
2020-12-28
Android搜索控件SearchView
搜索框控件一.默认效果该控件可通过继承的方式来实现样式上的扩展。二.使用方法创建布局 <com.example.kylinarm.searchviewdemo.components.view.seach.KylinSearchView android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="10dp" android:id="@+id/sv_default" > </com.example.kylinarm.searchviewdemo.components.view.seach.KylinSearchView>自定义属性<!-- 搜索框 --> <declare-styleable name="kylin_search_style"> <attr name="img_src" format="reference"/><!-- 图片地址 --> <attr name="img_size" format="dimension"/><!-- 图片大小 --> <attr name="img_visibility" format="boolean"/><!-- 图片显示/隐藏 --> <attr name="show_location" format="enum"> <enum name="left" value="0"/> <enum name="right" value="2"/> <enum name="centre" value="1"/> </attr> <attr name="edt_hint" format="string"/><!-- 提示文字 --> <attr name="edt_size" format="dimension"/><!-- 提示文字大小 --> <attr name="edt_hint_color" format="color"/><!-- 提示文字的颜色 --> <attr name="search_backgroup" format="reference"/><!-- 搜索框背景 --> <attr name="search_padding" format="reference"/><!-- 搜索框背景 --> </declare-styleable>例如<com.example.kylinarm.searchviewdemo.components.view.seach.KylinSearchView android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="10dp" android:id="@+id/sv_default" app:edt_hint = "搜索" app:edt_hint_color = "#336688" > </com.example.kylinarm.searchviewdemo.components.view.seach.KylinSearchView>使用方法KylinSearchView searchViewDemo = (KylinSearchView) findViewById(R.id.sv_default);监听搜索(默认软键盘回车搜索)searchViewDemo.setOnSearchListener(this); //实现OnSearchListener接口获取搜索框内容searchViewDemo.getSearchContent();清空搜索框searchViewDemo.clearSearch()让搜索框失去焦点searchViewDemo.lostRocus();执行搜索操作searchViewDemo.search();扩展封装时只定义了一些比较常用的方法,如果有其它需求,比如说搜索时改变图片图标或者文字颜色之类的,而组件内部并没用提供这些方法,为了考虑方便扩展,开发者可以从外部获取到搜索框、提示图标、输入框三个对象。searchViewDemo.getSearchEditText(); // 返回输入框 searchViewDemo.getSearchImageView(); // 返回图标 searchViewDemo.getSearchFrameView(); // 返回搜索框自定义样式可以通过继承的方式实现自定义样,比如说demo中的仿微信搜索框public class WxSearchView extends KylinSearchView{ private RelativeLayout searchFrame; private EditText edtSearch; private ImageView ivSearch; public WxSearchView(Context context) { super(context); } public WxSearchView(Context context, AttributeSet attrs) { super(context, attrs); } @Override public int getLayoutId() { return R.layout.layout_wx_search; } @Override public void initChildView() { searchFrame = seachView.findViewById(R.id.rl_content_wx); edtSearch = seachView.findViewById(R.id.edt_search_wx); ivSearch = seachView.findViewById(R.id.iv_search_wx); } @Override public ImageView getImageView() { return ivSearch; } @Override public EditText getEditText() { return edtSearch; } @Override public RelativeLayout getSearchFrame() { return searchFrame; } }子类要重写SearchExtendImpl接口的所有方法getImageView() 、 getEditText() 、 getSearchFrame()需要分别返回三个对象给父类。三.代码文档https://www.jianshu.com/p/353a87f60bb6
2020年12月28日
1,989 阅读
0 评论
25 点赞
2020-12-28
android 连接蓝牙打印机 BluetoothAdapter
android 连接蓝牙打印机 BluetoothAdapter源码下载地址https://github.com/yylxy/BluetoothText.gitpublic class PrintActivity extends AppCompatActivity { //设备列表 private ListView listView; private ArrayList<PrintBean> mBluetoothDevicesDatas; private PrintAdapter adapter; //蓝牙适配器 private BluetoothAdapter mBluetoothAdapter; //请求的code public static final int REQUEST_ENABLE_BT = 1; private Switch mSwitch; private FloatingActionButton mFloatingActionButton; private ProgressBar mProgressBar; private Toolbar toolbar; private TextView searchHint; /** * 启动打印页面 * * @param printContent 要打印的内容 */ public static void starUi(Context context, String printContent) { Intent intent = new Intent(context, PrintActivity.class); intent.putExtra("id", id); intent.putExtra("printContent", printContent); context.startActivity(intent); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //广播注册 IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); registerReceiver(mReceiver, filter); // Don't forget to unregister during onDestroy //初始化 mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); mSwitch = (Switch) findViewById(R.id.switch1); mFloatingActionButton = (FloatingActionButton) findViewById(R.id.floatingActionButton); mProgressBar = (ProgressBar) findViewById(R.id.progressBar3); toolbar = (Toolbar) findViewById(R.id.toolbar); searchHint = (TextView) findViewById(R.id.searchHint); toolbar.setTitle("选择打印设备"); listView = (ListView) findViewById(R.id.listView); mBluetoothDevicesDatas = new ArrayList<>(); String printContent=getIntent().getStringExtra("printContent"); adapter = new PrintAdapter(this, mBluetoothDevicesDatas, TextUtils.isEmpty(printContent)?"123456789完\n\n\n":printContent); listView.setAdapter(adapter); chechBluetooth(); addViewListener(); } /** * 判断有没有开启蓝牙 */ private void chechBluetooth() { //没有开启蓝牙 if (mBluetoothAdapter != null) { if (!mBluetoothAdapter.isEnabled()) { Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); // 设置蓝牙可见性,最多300秒 intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 20); startActivityForResult(intent, REQUEST_ENABLE_BT); setViewStatus(true); //开启蓝牙 } else { searchDevices(); setViewStatus(true); mSwitch.setChecked(true); } } } /** * 搜索状态调整 * * @param isSearch 是否开始搜索 */ private void setViewStatus(boolean isSearch) { if (isSearch) { mFloatingActionButton.setVisibility(View.GONE); searchHint.setVisibility(View.VISIBLE); mProgressBar.setVisibility(View.VISIBLE); } else { mFloatingActionButton.setVisibility(View.VISIBLE); mProgressBar.setVisibility(View.GONE); searchHint.setVisibility(View.GONE); } } /** * 添加View的监听 */ private void addViewListener() { //蓝牙的状态 mSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if (isChecked) { openBluetooth(); setViewStatus(true); } else { closeBluetooth(); } } }); //重新搜索 mFloatingActionButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (mSwitch.isChecked()) { searchDevices(); setViewStatus(true); } else { openBluetooth(); setViewStatus(true); } } }); toolbar.setNavigationIcon(R.drawable.ic_arrow_back_black_24dp); toolbar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Toast.makeText(PrintActivity.this, "88", Toast.LENGTH_SHORT).show(); } }); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == RESULT_OK && requestCode == REQUEST_ENABLE_BT) { Log.e("text", "开启蓝牙"); searchDevices(); mSwitch.setChecked(true); mBluetoothDevicesDatas.clear(); adapter.notifyDataSetChanged(); } else if (resultCode == RESULT_CANCELED && requestCode == REQUEST_ENABLE_BT) { Log.e("text", "没有开启蓝牙"); mSwitch.setChecked(false); setViewStatus(false); } } /** * 打开蓝牙 */ public void openBluetooth() { Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); // 设置蓝牙可见性,最多300秒 intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 20); startActivityForResult(intent, REQUEST_ENABLE_BT); } /** * 关闭蓝牙 */ public void closeBluetooth() { mBluetoothAdapter.disable(); } /** * 搜索蓝牙设备 */ public void searchDevices() { mBluetoothDevicesDatas.clear(); adapter.notifyDataSetChanged(); //开始搜索蓝牙设备 mBluetoothAdapter.startDiscovery(); } /** * 通过广播搜索蓝牙设备 */ private final BroadcastReceiver mReceiver = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { String action = intent.getAction(); // 把搜索的设置添加到集合中 if (BluetoothDevice.ACTION_FOUND.equals(action)) { BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); //已经匹配的设备 if (device.getBondState() == BluetoothDevice.BOND_BONDED) { addBluetoothDevice(device); //没有匹配的设备 } else { addBluetoothDevice(device); } adapter.notifyDataSetChanged(); //搜索完成 } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) { setViewStatus(false); } } /** * 添加数据 * @param device 蓝牙设置对象 */ private void addBluetoothDevice(BluetoothDevice device) { for (int i = 0; i < mBluetoothDevicesDatas.size(); i++) { if (device.getAddress().equals(mBluetoothDevicesDatas.get(i).getAddress())) { mBluetoothDevicesDatas.remove(i); } } if (device.getBondState() == BluetoothDevice.BOND_BONDED && device.getBluetoothClass().getDeviceClass() == PRINT_TYPE) { mBluetoothDevicesDatas.add(0, new PrintBean(device)); } else { mBluetoothDevicesDatas.add(new PrintBean(device)); } } }; }class PrintAdapter extends BaseAdapter { private ArrayList<PrintBean> mBluetoothDevicesDatas; private Context mContext; //蓝牙适配器 private BluetoothAdapter mBluetoothAdapter; //蓝牙socket对象 private BluetoothSocket mmSocket; private UUID uuid; //打印的输出流 private static OutputStream outputStream = null; //搜索弹窗提示 ProgressDialog progressDialog = null; private final int exceptionCod = 100; //打印的内容 private String mPrintContent; //在打印异常时更新ui Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); if (msg.what == exceptionCod) { Toast.makeText(mContext, "打印发送失败,请稍后再试", Toast.LENGTH_SHORT).show(); if (progressDialog != null) { progressDialog.dismiss(); } } } }; /** * @param context 上下文 * @param mBluetoothDevicesDatas 设备列表 * @param printContent 打印的内容 */ public PrintAdapter(Context context, ArrayList<PrintBean> mBluetoothDevicesDatas, String printContent) { this.mBluetoothDevicesDatas = mBluetoothDevicesDatas; mContext = context; mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); mPrintContent = printContent; uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); } public int getCount() { return mBluetoothDevicesDatas.size(); } @Override public Object getItem(int position) { return position; } @Override public long getItemId(int position) { return position; } @Override public View getView(final int position, View convertView, ViewGroup parent) { convertView = LayoutInflater.from(mContext).inflate(R.layout.itme, null); View icon = convertView.findViewById(R.id.icon); TextView name = (TextView) convertView.findViewById(R.id.name); TextView address = (TextView) convertView.findViewById(R.id.address); TextView start = (TextView) convertView.findViewById(R.id.start); final PrintBean dataBean = mBluetoothDevicesDatas.get(position); icon.setBackgroundResource(dataBean.getTypeIcon()); name.setText(dataBean.name); address.setText(dataBean.isConnect ? "已连接" : "未连接"); start.setText(dataBean.getDeviceType(start)); //点击连接与打印 convertView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { try { //如果已经连接并且是打印机 if (dataBean.isConnect && dataBean.getType() == PRINT_TYPE) { if (mBluetoothAdapter.isEnabled()) { new ConnectThread(mBluetoothAdapter.getRemoteDevice(dataBean.address)).start(); progressDialog = ProgressDialog.show(mContext, "提示", "正在打印...", true); } else { Toast.makeText(mContext, "蓝牙没有打开", Toast.LENGTH_SHORT).show(); } //没有连接 } else { //是打印机 if (dataBean.getType() == PRINT_TYPE) { setConnect(mBluetoothAdapter.getRemoteDevice(dataBean.address), position); //不是打印机 } else { Toast.makeText(mContext, "该设备不是打印机", Toast.LENGTH_SHORT).show(); } } } catch (Exception e) { e.printStackTrace(); } } }); return convertView; } /** * 匹配设备 * * @param device 设备 */ private void setConnect(BluetoothDevice device, int position) { try { Method createBondMethod = BluetoothDevice.class.getMethod("createBond"); createBondMethod.invoke(device); mBluetoothDevicesDatas.get(position).setConnect(true); notifyDataSetChanged(); } catch (Exception e) { e.printStackTrace(); } } /** * 发送数据 */ public void send(String sendData) { try { byte[] data = sendData.getBytes("gbk"); outputStream.write(data, 0, data.length); outputStream.flush(); outputStream.close(); progressDialog.dismiss(); } catch (IOException e) { e.printStackTrace(); handler.sendEmptyMessage(exceptionCod); // 向Handler发送消息,更新UI } } /** * 连接为客户端 */ private class ConnectThread extends Thread { public ConnectThread(BluetoothDevice device) { try { mmSocket = device.createRfcommSocketToServiceRecord(uuid); } catch (IOException e) { e.printStackTrace(); } } public void run() { //取消的发现,因为它将减缓连接 mBluetoothAdapter.cancelDiscovery(); try { //连接socket mmSocket.connect(); //连接成功获取输出流 outputStream = mmSocket.getOutputStream(); send(mPrintContent); } catch (Exception connectException) { Log.e("test", "连接失败"); connectException.printStackTrace(); //异常时发消息更新UI Message msg = new Message(); msg.what = exceptionCod; // 向Handler发送消息,更新UI handler.sendMessage(msg); try { mmSocket.close(); } catch (Exception closeException) { closeException.printStackTrace(); } return; } } } }
2020年12月28日
1,358 阅读
0 评论
23 点赞
2020-12-28
vue-big-screen: 一个基于 vue+datav+Echart 框架的大数据可视化(大屏展示)模板
一、项目描述React 版本请点击这里查看,全新界面超级好看!!!(o ゚ v ゚)ノ一个基于 Vue、Datav、Echart 框架的 " 数据大屏项目 ",通过 Vue 组件实现数据动态刷新渲染,内部图表可实现自由替换。部分图表使用 DataV 自带组件,可进行更改,详情请点击下方 DataV 文档。项目需要全屏展示(按 F11)。项目部分区域使用了全局注册方式,增加了打包体积,在实际运用中请使用 按需引入。拉取项目之后,建议按照自己的功能区域重命名文件,现以简单的位置进行区分。项目环境:Vue-cli-3.0、DataV-2.7.3、Echarts-4.6.0(如果5.x版本有问题,请切换到4.x版本)、Webpack-4.0、Npm-6.13、Node-v12.16。请拉取 master 分支的代码,其余是开发分支。友情链接:Vue 官方文档DataV 官方文档echarts 实例,echarts API 文档项目 gitee 地址(国内速度快)二、主要文件介绍文件作用/功能main.js主目录文件,引入 Echart/DataV 等文件utils工具函数与 mixins 函数等views/ index.vue项目主结构views/其余文件界面各个区域组件(按照位置来命名)assets静态资源目录,放置 logo 与背景图片assets / style.scss通用 CSS 文件,全局项目快捷样式调节assets / index.scssIndex 界面的 CSS 文件components/echart所有 echart 图表(按照位置来命名)common/...全局封装的 ECharts 和 flexible 插件代码(适配屏幕尺寸,可定制化修改)三、使用介绍启动项目需要提前安装好 nodejs 与 npm,下载项目后在项目主目录下运行 npm/cnpm install 拉取依赖包。安装完依赖包之后然后使用 vue-cli 或者直接使用命令npm run serve,就可以启动项目,启动项目后需要手动全屏(按 F11)。如果编译项目的时候提示没有 DataV 框架的依赖,输入 npm install @jiaminghi/data-view 或者 yarn add @jiaminghi/data-view 进行手动安装。封装组件渲染图表所有的 ECharts 图表都是基于 common/echart/index.vue 封装组件创建的,已经对数据和屏幕改动进行了监听,能够动态渲染图表数据和大小。在监听窗口小大的模块,使用了防抖函数来控制更新频率,节约浏览器性能。项目配置了默认的 ECharts 图表样式,文件地址:common/echart/theme.json。封装的渲染图表组件支持传入以下参数,可根据业务需求自行添加/删除。参数名称类型作用/功能 idString唯一 id,渲染图表的节点(非必填,使用了 $el)classNameStringclass样式名称(非必填)optionsObjectECharts 配置(必填)heightString图表高度(建议填)widthString图表宽度(建议填)动态渲染图表动态渲染图表案例为 components 目录下各个图表组件,index 文件负责数据获取和处理,chart 文件负责监听和数据渲染。chart 文件的主要逻辑为:<template> <div> <Echart :options="options" id="id" height="height" width="width" ></Echart> </div> </template> <script> // 引入封装组件 import Echart from '@/common/echart' export default { // 定义配置数据 data(){ return { options: {}}}, // 声明组件 components: { Echart}, // 接收数据 props: { cdata: { type: Object, default: () => ({}) }, }, // 进行监听,也可以使用 computed 计算属性实现此功能 watch: { cdata: { handler (newData) { this.options ={ // 这里编写 ECharts 配置 } }, // 立即监听 immediate: true, // 深度监听 deep: true } } }; </script>复用图表组件复用图表组件案例为中间部分的 任务通过率与任务达标率 模块,两个图表类似,区别在于颜色和主要渲染数据。只需要传入对应的唯一 id 和样式,然后在复用的组件 components/echart/center/centerChartRate 里进行接收并在对应位置赋值即可。如:在调用处 views/center.vue 里去定义好数据并传入组件//组件调用 <span>今日任务通过率</span> <centerChart :id="rate[0].id" :tips="rate[0].tips" :colorObj="rate[0].colorData" /> <span>今日任务达标率</span> <centerChart :id="rate[1].id" :tips="rate[1].tips" :colorObj="rate[1].colorData" /> ... import centerChart from "@/components/echart/center/centerChartRate"; data() { return { rate: [ { id: "centerRate1", tips: 60, ... }, { id: "centerRate2", tips: 40, colorData: { ... } } ] } }更换边框边框是使用了 DataV 自带的组件,只需要去 views 目录下去寻找对应的位置去查找并替换就可以,具体的种类请去 DavaV 官网查看如:<dv-border-box-1></dv-border-box-1> <dv-border-box-2></dv-border-box-2> <dv-border-box-3></dv-border-box-3>更换图表直接进入 components/echart 下的文件修改成你要的 echarts 模样,可以去echarts 官方社区里面查看案例。Mixins 解决自适应适配功能使用 mixins 注入解决了界面大小变动图表自适应适配的功能,函数在 utils/resizeMixins.js 中,应用在 common/echart/index.vue 的封装渲染组件,主要是对 this.chart 进行了功能注入。屏幕适配本项目借助了 flexible 插件,通过改变 rem 的值来进行适配,原设计为 1920px。 ,适配区间为:1366px ~ 2560px,本项目有根据实际情况进行源文件的更改,小屏幕(如:宽为 1366px)需要自己舍弃部分动态组件进行适配,如'动态文字变换组件'会影响布局,需要手动换成一般节点,// flexible文件位置: `common/flexible.js`,修改部分如下 function refreshRem() { var width = docEl.getBoundingClientRect().width; // 最小1366px,最大适配2560px if (width / dpr < 1366) { width = 1366 * dpr; } else if (width / dpr > 2560) { width = 2560 * dpr; } // 原项目是1920px我设置成24等份,这样1rem就是80px var rem = width / 24; docEl.style.fontSize = rem + 'px'; flexible.rem = win.rem = rem; }请求数据现在的项目未使用前后端数据请求,建议使用 axios 进行数据请求,在 main.js 位置进行全局配置。axios 的 main.js 配置参考范例(因人而异)import axios from 'axios'; //把方法放到vue的原型上,这样就可以全局使用了 Vue.prototype.$http = axios.create({ //设置20秒超时时间 timeout: 20000, baseURL: 'http://172.0.0.1:80080', //这里写后端地址 });四、更新情况增加了 Echart 组件复用的功能,如:中间任务达标率的两个百分比图使用的是同一个组件。修复了头部右侧的图案条不对称的问题。修复屏幕适配问题,更换了所有的尺寸单位,统一使用 rem。使用 Mixins 注入图表响应式代码。vue-awesome 改成按需引入的方式。封装渲染函数,抽离了数据使逻辑更加清晰。新增地图组件,并添加自动轮播功能五、其余这个项目是个人的作品,难免会有问题和 BUG,如果有问题请进行评论,我也会尽力去更新,自己也在前端学习的路上,欢迎交流,非常感谢!
2020年12月28日
1,857 阅读
0 评论
0 点赞
2020-12-28
java8 list统计(求和、最大、最小、平均)
list.stream().mapToDouble(User::getHeight).sum()//和 list.stream().mapToDouble(User::getHeight).max()//最大 list.stream().mapToDouble(User::getHeight).min()//最小 list.stream().mapToDouble(User::getHeight).average()//平均值
2020年12月28日
1,286 阅读
0 评论
0 点赞
2020-12-26
jetbrains全家桶2020.12.26破解失败临时解决方法
jetbrains全家桶破解于2020年12月26日再次失效,大家可以通过以下激活码进行激活。UD5T6WF5YW-eyJsaWNlbnNlSWQiOiJVRDVUNldGNVlXIiwibGljZW5zZWVOYW1lIjoi5rC45LmF5YWN6LS577yaIGxvb2tkaXbCt2NvbSIsImFzc2lnbmVlTmFtZSI6IiIsImFzc2lnbmVlRW1haWwiOiIiLCJsaWNlbnNlUmVzdHJpY3Rpb24iOiIiLCJjaGVja0NvbmN1cnJlbnRVc2UiOmZhbHNlLCJwcm9kdWN0cyI6W3siY29kZSI6IkRDIiwicGFpZFVwVG8iOiIyMDIxLTAxLTIwIiwiZXh0ZW5kZWQiOmZhbHNlfSx7ImNvZGUiOiJJSSIsInBhaWRVcFRvIjoiMjAyMS0wMS0yMCIsImV4dGVuZGVkIjpmYWxzZX0seyJjb2RlIjoiREIiLCJwYWlkVXBUbyI6IjIwMjEtMDEtMjAiLCJleHRlbmRlZCI6ZmFsc2V9LHsiY29kZSI6IlJNIiwicGFpZFVwVG8iOiIyMDIxLTAxLTIwIiwiZXh0ZW5kZWQiOmZhbHNlfSx7ImNvZGUiOiJXUyIsInBhaWRVcFRvIjoiMjAyMS0wMS0yMCIsImV4dGVuZGVkIjpmYWxzZX0seyJjb2RlIjoiUlNWIiwicGFpZFVwVG8iOiIyMDIxLTAxLTIwIiwiZXh0ZW5kZWQiOnRydWV9LHsiY29kZSI6IlJTVSIsInBhaWRVcFRvIjoiMjAyMS0wMS0yMCIsImV4dGVuZGVkIjpmYWxzZX0seyJjb2RlIjoiUEMiLCJwYWlkVXBUbyI6IjIwMjEtMDEtMjAiLCJleHRlbmRlZCI6ZmFsc2V9LHsiY29kZSI6IlJDIiwicGFpZFVwVG8iOiIyMDIxLTAxLTIwIiwiZXh0ZW5kZWQiOmZhbHNlfSx7ImNvZGUiOiJSRCIsInBhaWRVcFRvIjoiMjAyMS0wMS0yMCIsImV4dGVuZGVkIjpmYWxzZX0seyJjb2RlIjoiRE0iLCJwYWlkVXBUbyI6IjIwMjEtMDEtMjAiLCJleHRlbmRlZCI6ZmFsc2V9LHsiY29kZSI6IkNMIiwicGFpZFVwVG8iOiIyMDIxLTAxLTIwIiwiZXh0ZW5kZWQiOmZhbHNlfSx7ImNvZGUiOiJSUzAiLCJwYWlkVXBUbyI6IjIwMjEtMDEtMjAiLCJleHRlbmRlZCI6ZmFsc2V9LHsiY29kZSI6IlJTQyIsInBhaWRVcFRvIjoiMjAyMS0wMS0yMCIsImV4dGVuZGVkIjp0cnVlfSx7ImNvZGUiOiJHTyIsInBhaWRVcFRvIjoiMjAyMS0wMS0yMCIsImV4dGVuZGVkIjpmYWxzZX0seyJjb2RlIjoiUlNGIiwicGFpZFVwVG8iOiIyMDIxLTAxLTIwIiwiZXh0ZW5kZWQiOnRydWV9LHsiY29kZSI6IlBTIiwicGFpZFVwVG8iOiIyMDIxLTAxLTIwIiwiZXh0ZW5kZWQiOmZhbHNlfSx7ImNvZGUiOiJEUE4iLCJwYWlkVXBUbyI6IjIwMjEtMDEtMjAiLCJleHRlbmRlZCI6ZmFsc2V9LHsiY29kZSI6IkFDIiwicGFpZFVwVG8iOiIyMDIxLTAxLTIwIiwiZXh0ZW5kZWQiOmZhbHNlfSx7ImNvZGUiOiJQREIiLCJwYWlkVXBUbyI6IjIwMjEtMDEtMjAiLCJleHRlbmRlZCI6dHJ1ZX0seyJjb2RlIjoiUFdTIiwicGFpZFVwVG8iOiIyMDIxLTAxLTIwIiwiZXh0ZW5kZWQiOnRydWV9LHsiY29kZSI6IlBHTyIsInBhaWRVcFRvIjoiMjAyMS0wMS0yMCIsImV4dGVuZGVkIjp0cnVlfSx7ImNvZGUiOiJQUFMiLCJwYWlkVXBUbyI6IjIwMjEtMDEtMjAiLCJleHRlbmRlZCI6dHJ1ZX0seyJjb2RlIjoiUFBDIiwicGFpZFVwVG8iOiIyMDIxLTAxLTIwIiwiZXh0ZW5kZWQiOnRydWV9LHsiY29kZSI6IlBSQiIsInBhaWRVcFRvIjoiMjAyMS0wMS0yMCIsImV4dGVuZGVkIjp0cnVlfSx7ImNvZGUiOiJQU1ciLCJwYWlkVXBUbyI6IjIwMjEtMDEtMjAiLCJleHRlbmRlZCI6dHJ1ZX0seyJjb2RlIjoiUFNJIiwicGFpZFVwVG8iOiIyMDIxLTAxLTIwIiwiZXh0ZW5kZWQiOnRydWV9LHsiY29kZSI6IkRQIiwicGFpZFVwVG8iOiIyMDIxLTAxLTIwIiwiZXh0ZW5kZWQiOnRydWV9LHsiY29kZSI6IlJTIiwicGFpZFVwVG8iOiIyMDIxLTAxLTIwIiwiZXh0ZW5kZWQiOnRydWV9XSwibWV0YWRhdGEiOiIwMTIwMjAxMjIxUFBBTTAwMDAwNSIsImhhc2giOiIyMTY1MjE2MC8wOi0xMzY3OTQ1NjAiLCJncmFjZVBlcmlvZERheXMiOjcsImF1dG9Qcm9sb25nYXRlZCI6ZmFsc2UsImlzQXV0b1Byb2xvbmdhdGVkIjpmYWxzZX0=-c1Kpo0VqL6BYALtXWauBc9E6NWpFv3l75uwkEW810fvOHBCWMRGA8BR8nXvLXRZHOIKYomGPElq3fmG9djn9ePXxwe8IdE960WBQjnGEVacLIA+CY7nGwZaRA78QnKke41oDciDfdZxri9nMXZnKPFy0MsJCwGiMkOcCwDCgxTVXgO+ZwIcsNdNV0UlpdVaOAvr2l8QD9gxAi1M1DxVWaS5N50UrreGbd1A9tYJr1vzM0Uqkfw4hpV4FrKrzISzSFiRVhp3X0W+PlwlTK3rh+JkD2fGyrDdAFZHwc5KWclZNZOdXneC9T8n37jcQQOFFsCtbID02hQhuvTz8ktypKw==-MIIETDCCAjSgAwIBAgIBDTANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1KZXRQcm9maWxlIENBMB4XDTIwMTAxOTA5MDU1M1oXDTIyMTAyMTA5MDU1M1owHzEdMBsGA1UEAwwUcHJvZDJ5LWZyb20tMjAyMDEwMTkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDCP4uk4SlVdA5nuA3DQC+NsEnZS9npFnO0zrmMWcz1++q2UWJNuGTh0rwi+3fUJIArfvVh7gNtIp93rxjtrQAuf4/Fa6sySp4c32MeFACfC0q+oUoWebhOIaYTYUxm4LAZ355vzt8YeDPmvWKxA81udqEk4gU9NNAOz1Um5/8LyR8SGsSc4EDBRSjcMWMwMkYSauGqGcEUK8WhfplsyF61lKSOFA6VmfUmeDK15rUWWLbOMKgn2cxFA98A+s74T9Oo96CU7rp/umDXvhnyhAXSukw/qCGOVhwKR8B6aeDtoBWQgjnvMtPgOUPRTPkPGbwPwwDkvAHYiuKJ7Bd2wH7rAgMBAAGjgZkwgZYwCQYDVR0TBAIwADAdBgNVHQ4EFgQUJNoRIpb1hUHAk0foMSNM9MCEAv8wSAYDVR0jBEEwP4AUo562SGdCEjZBvW3gubSgUouX8bOhHKQaMBgxFjAUBgNVBAMMDUpldFByb2ZpbGUgQ0GCCQDSbLGDsoN54TATBgNVHSUEDDAKBggrBgEFBQcDATALBgNVHQ8EBAMCBaAwDQYJKoZIhvcNAQELBQADggIBAB2J1ysRudbkqmkUFK8xqhiZaYPd30TlmCmSAaGJ0eBpvkVeqA2jGYhAQRqFiAlFC63JKvWvRZO1iRuWCEfUMkdqQ9VQPXziE/BlsOIgrL6RlJfuFcEZ8TK3syIfIGQZNCxYhLLUuet2HE6LJYPQ5c0jH4kDooRpcVZ4rBxNwddpctUO2te9UU5/FjhioZQsPvd92qOTsV+8Cyl2fvNhNKD1Uu9ff5AkVIQn4JU23ozdB/R5oUlebwaTE6WZNBs+TA/qPj+5/wi9NH71WRB0hqUoLI2AKKyiPw++FtN4Su1vsdDlrAzDj9ILjpjJKA1ImuVcG329/WTYIKysZ1CWK3zATg9BeCUPAV1pQy8ToXOq+RSYen6winZ2OO93eyHv2Iw5kbn1dqfBw1BuTE29V2FJKicJSu8iEOpfoafwJISXmz1wnnWL3V/0NxTulfWsXugOoLfv0ZIBP1xH9kmf22jjQ2JiHhQZP7ZDsreRrOeIQ/c4yR8IQvMLfC0WKQqrHu5ZzXTH4NO3CwGWSlTY74kE91zXB5mwWAx1jig+UXYc2w4RkVhy0//lOmVya/PEepuuTTI4+UJwC7qbVlh5zfhj8oTNUXgN0AOc+Q0/WFPl1aw5VV/VrO8FCoB15lFVlpKaQ1Yh+DVU8ke+rt9Th0BCHXe0uZOEmH0nOnH/0onD
2020年12月26日
1,286 阅读
0 评论
0 点赞
2020-12-25
同一nginx服务器部署多个vue项目
项目上使用了大屏,由于大屏的框架样式与业务系统存在冲突,所以决定单独拆分成两个独立的vue项目。一、项目信息首先两个项目,一个web存放的是业务系统,正常访问。另外一个bigscreen作为大屏使用,通过二级目录/bigScreen访问二、web项目处理web项目不需要特殊处理,正常build即可。三、bigscreen项目处理1. 修改配置文件vue.config.js打开项目根目录下的vue.config.js文件,修改public如下publicPath: process.env.NODE_ENV === "production" ? "/bigScreen" : "/",2. 修改src/router/index.js, 项目页面跳转路由const router = new VueRouter({ mode: "history", base: '/bigScreen', routes })3. 配置nginxnginx配置文件,添加如下节点location /bigScreen/ { alias /www/wwwroot/dotnetcore.com.cn/bigScreen/; index index.html index.htm; try_files $uri $uri/ /bigScreen/index.html; # 内部项目跳转路径 }四、项目部署原始项目,还是放到根目录。bigScreen在网站根目录下创建bigScreen文件夹,并将生成的文件上传到bigScreen目录下。
2020年12月25日
1,375 阅读
0 评论
1 点赞
2020-12-20
HeiPermission:一句代码搞定 Android M 动态权限检测
项目地址建议通过源码的方式引入。项目地址https://github.com/forJrking/HeiPermission使用方式导入permlib到Project中,app添加库依赖。(建议拷贝源码,可根据需求定制)奇淫技巧:checkPermission(CheckPermListener listener, int resString, String... mPerms) - listener: 权限全部通过接口回调,只检测没有后续行为可 null - resString: 权限用途的说明提示(引导用户开启权限) - mPerms: 申请的高危权限组(可同时申请多个)最简单的使用方式Activity中:首先需要检测权限的 Activity extends PermissionActivity checkPermission(new CheckPermListener() { @Override public void superPermission() { TODO : 需要权限去完成的功能 } },R.string.camera, Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE);Fragment中:首先Fragment依存的 Activity extends PermissionActivit ((PermissionActivity)getActivity()).checkPermission( new PermissionActivity.CheckPermListener() { @Override public void superPermission() { TODO : 需要权限去完成的功能 } },R.string.camera, Manifest.permission.CAMERA);
2020年12月20日
1,320 阅读
0 评论
24 点赞
1
...
30
31
32
...
53