和大佬学的
先把你需要的模版文档弄好成docx格式,再把后缀改成.zip格式 获取里面的document.xml文件,在xml中把你要替换的参数写成表达式如:${productName},在项目中通过代码填充productName参数,进行测试)
也可以把表达式先写到docx文件中,在改后缀。。。亲测
和大佬学的
先把你需要的模版文档弄好成docx格式,再把后缀改成.zip格式 获取里面的document.xml文件,在xml中把你要替换的参数写成表达式如:${productName},在项目中通过代码填充productName参数,进行测试)
也可以把表达式先写到docx文件中,在改后缀。。。亲测
如果redis数据被丢失,则从数据库查询出最大数值保存到redis在自增
// 生成递增的货号逻辑
public String generateProductCode() {
lock.lock(); // 加锁,确保多线程安全
try {
// 从 Redis 获取当前货号,如果 Redis 中不存在,初始化货号
String currentCodeStr = redisTemplate.opsForValue().get(PRODUCT_CODE_KEY);
if (currentCodeStr == null) {
// 从数据库中获取当前最大的货号
Integer maxCode = productMapper.findMaxProductCode();
if (maxCode == null) {
maxCode = 0; // 如果数据库中没有数据,从 0 开始
}
// 初始化 Redis 中的货号为数据库中的最大值
redisTemplate.opsForValue().set(PRODUCT_CODE_KEY, maxCode.toString());
}
// 使用 Redis 的 INCR 命令自增货号
Long newCode = redisTemplate.opsForValue().increment(PRODUCT_CODE_KEY);
return String.format("%08d", newCode); // 格式化为 8 位数字
} finally {
lock.unlock(); // 解锁
}
}
// 生成递增的货号
String productCode = generateProductCode();
product.setItemNumberPrefix("ZML");
product.setItemNumber(productCode);
private static final String PRODUCT_CODE_KEY = "product:code"; // Redis 中货号的 key
private final Lock lock = new ReentrantLock(); // 创建一个 ReentrantLock 锁
@Autowired
private StringRedisTemplate redisTemplate;
// 查询当前数据库中最大的货号
@Select("SELECT MAX(p.item_number) FROM Product p")
Integer findMaxProductCode();
为了方便查询我是把编号和编号前缀分成了两个字段保存
private String itemNumberPrefix;
@ApiModelProperty(value = "商品货号")
private String itemNumber;
公司项目用的微服务架构
苦于每次需要手动改数据库表
然后我在想能不能集成一个数据库版本管理工具
调查选择flyway
因为项目是分布式的,每个服务有一个数据库
然后我的做法是创建一个共同的子工程来统一管理sql文件
然后再resources目录创建每个工程对应的文件夹
#前缀: V 代表版本变迁(Versioned Migrations), U 代表撤销变迁(Undo Migrations), R 代表可重复变迁(Repeatable Migrations)
#版本号: 唯一的版本号,比如V1.0.1
#分隔符: __ (两个下划线)
#描述信息: 描述信息
#后缀: .sql
flyway:
# 是否开启flyway
enabled: true
encoding: utf-8
# 是否禁用数据库清理
clean-disabled: true
# 若连接的数据库非空库,是否初始化
# 当迁移时发现目标schema非空,而且带有没有元数据的表时,是否自动执行基准迁移,默认false.
baseline-on-migrate: true
# sql脚本文件名前缀,默认大写V
sql-migration-prefix: V
# sql脚本文件名称的分隔符,默认2个下划线__
sql-migration-separator: __
# 迁移sql脚本文件名称的后缀
sql-migration-suffixes: .sql
# metadata 版本控制信息表 默认 flyway_schema_history
table: flyway_schema_history
# 指定 baseline 的版本号,默认值为 1, 低于该版本号的 SQL 文件, migrate 时会被忽略
baseline-version: 1
然后再每个服务的配置文件中写入
flyway:
# 默认存放sql脚本目录,默认为db/migration
locations: classpath:db/migration/im
指定每个工程sql位置
即可。。。。
sql文件的命名规则如下:
V1.0.0__create_user.sql
写了一个接口发现不能调用 一直在做尝试发现无果
偶然想起以前开始时用dubbo做注册中心传输数据时
实体类要序列化一下
浪费我三十分钟
实体类实现了implements Serializable后就可以了
。。。。。
。。。。
。。。。
首先小程序端的地图轨迹显示问题
如果使用web-view组件的话,地图会沾满满屏
所以要做小程序地图就必须使用在小程序用web-view组件 中引入项目h5页面然后再h5页面用iframe去引入地图轨迹url即可
如果H5页面想改名称的话可以用 来修改名称
mounted() {
document.title = "物流信息";
},
H5代码
<template>
<div class="app-container">
<el-card class="box-card" shadow="hover">
<span>{{ companyName }} {{ expressNumber }}</span>
<span style="color: #ff5502; margin-left: 12px" @click="handleCopyText()">复制</span>
</el-card>
<el-card class="box-card" shadow="hover">
<div slot="header" class="clearfix">
<span>物流轨迹</span>
</div>
<div v-if="iframeMapUrl">
<iframe id="iframe" width="100%" height="600px" frameborder="0" allowfullscreen :src="iframeMapUrl" />
</div>
<div v-else class="empty-space">暂无物流信息</div>
</el-card>
<el-card class="box-card" shadow="hover">
<div slot="header" class="clearfix">
<span>物流信息</span>
</div>
<template v-if="limitedProgressInfo">
<div class="view-more-button">
<el-button type="text" @click="showAllProgressInfo">{{ showLimitedProgress ? '查看详情' : '收起详情' }}
<i :class="showLimitedProgress ? 'el-icon-arrow-down' : 'el-icon-arrow-up'"></i></el-button>
</div>
<el-timeline>
<el-timeline-item v-for="(activity, index) in limitedProgressInfo" :key="index"
:timestamp="activity.time">
<template v-if="activity.status === '揽收'">
<span style="color: #67c23a">已揽收:</span>
<span>{{ activity.context }}</span>
</template>
<template v-else-if="activity.status === '在途'">
<span style="color: #409eff">运输中:</span>
<span>{{ activity.context }}</span>
</template>
<template v-else-if="activity.status === '派件'">
<span style="color: #f56c6c">派件中:</span>
<span>{{ activity.context }}</span>
</template>
<template v-else-if="activity.status === '签收'">
<span style="color: #67c23a">已签收:</span>
<span>{{ activity.context }}</span>
</template>
<template v-else-if="activity.status === '退回'">
<span style="color: #909399">已退回:</span>
<span>{{ activity.context }}</span>
</template>
</el-timeline-item>
</el-timeline>
</template>
<div v-else class="empty-space">暂无物流信息</div>
</el-card>
</div>
</template>
<script>
import { deliveryCheck } from '@/api/mall'
export default {
name: 'logisticsInfoh5',
components: {},
// metaInfo: {
// title: '物流信息'
// },
props: {
type: {
default: 1,
type: Number
}
},
mounted() {
document.title = "物流信息";
},
computed: {
},
data() {
return {
post_name: '韵达快递', //快递名称
logo: 'https://cdn.kuaidi100.com/images/all/56/yunda.png', //快递logo
exp_phone: '95546', //快递电话
progressVisible: false,
companyName: null,
expressNumber: null,
companyNameExpressNumber: this.companyName + this.expressNumber,
iframeMapUrl: null,
progressInfo: null, // 完整的物流信息数据
limitedProgressInfo: null, // 展示的部分物流信息数据
showLimitedProgress: true // 控制是否只显示部分物流信息
}
},
watch: {},
created() {
this.showProgressBox()
},
methods: {
//复制
handleCopyText() {
// 创建一个 Input标签
const cInput = document.createElement('input')
cInput.value = this.companyName + this.expressNumber
document.body.appendChild(cInput)
cInput.select() // 选取文本域内容;
// 执行浏览器复制命令
// 复制命令会将当前选中的内容复制到剪切板中(这里就是创建的input标签)
// Input要在正常的编辑状态下原生复制方法才会生效
document.execCommand('Copy')
this.$message.success('复制成功')
/// 复制成功后再将构造的标签 移除
cInput.remove()
},
//展示物流进度的对话框
async showProgressBox() {
const params = {
orderNum: 3644
}
deliveryCheck(params)
.then((res) => {
this.companyName = res.data.companyName
this.expressNumber = res.data.expressNumber
if (res.code !== 200) {
return this.$message.error('获取物流进度失败!')
}
if (res.data.queryTrackResp) {
this.progressInfo = res.data.queryTrackResp.data
}
if (res.data.queryTrackMapResp) {
this.iframeMapUrl = res.data.queryTrackMapResp.trailUrl
}
if (this.progressInfo) {
this.limitedProgressInfo = this.progressInfo.slice(0, 3)
}
})
.catch((error) => {
console.error(error)
})
},
showAllProgressInfo() {
this.limitedProgressInfo = this.progressInfo
this.showLimitedProgress = !this.showLimitedProgress
if (this.showLimitedProgress) {
this.limitedProgressInfo = this.progressInfo.slice(0, 3)
}
}
}
}
</script>
<style lang="scss" scoped>
.app-container {
background-color: #f9f7f8;
}
.el-row {
line-height: 2;
font-size: 15px;
}
.box-card {
margin: 20px 0;
.flexItem {
display: flex;
align-items: center;
.fuhao {
margin-right: 3px;
font-size: 16px;
color: red;
}
.el-input {
width: auto;
flex: 1;
}
}
}
.custom-input {
width: 300px;
/* 设置输入框的宽度为300px */
}
.view-more-button {
display: flex;
justify-content: flex-end;
}
</style>
小程序代码: