同步6/16

This commit is contained in:
Zy
2026-06-01 18:12:58 +08:00
parent 38274ab612
commit 50e7b14fd6
183 changed files with 8956 additions and 4803 deletions

View File

@@ -0,0 +1,374 @@
<template>
<div class="p-2 h-full flex flex-col">
<pageheader></pageheader>
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<el-form-item label="应用名称" prop="channel">
<el-select v-model="queryParams.channel" placeholder="请选择">
<el-option label="花开物业App" value="resident"></el-option>
<el-option label="花开管家App" value="butler"></el-option>
</el-select>
</el-form-item>
<el-form-item label="应用类型" prop="platform">
<el-select v-model="queryParams.platform" placeholder="请选择">
<el-option label="iOS" value="ios"></el-option>
<el-option label="Android" value="android"></el-option>
</el-select>
</el-form-item>
<el-form-item label="版本号" prop="versionCode">
<el-input v-model="queryParams.versionCode" placeholder="请输入版本号" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="版本名称" prop="versionName">
<el-input v-model="queryParams.versionName" placeholder="请输入版本名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</transition>
<el-card shadow="never" class="flex-1">
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['system:version:add']">新增</el-button>
</el-col>
<!-- <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar> -->
</el-row>
</template>
<el-table
:default-sort="{ prop: 'versionCode', order: 'descending' }"
v-loading="loading"
border
:data="versionList"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="应用名称" sortable align="center" prop="channel">
<template #default="scope">
<span v-if="scope.row.channel === 'resident'">花开物业App</span>
<span v-else-if="scope.row.channel === 'butler'">花开管家App</span>
</template>
</el-table-column>
<el-table-column label="版本类型" align="center" prop="platform">
<template #default="scope">
<el-tag type="success" v-if="scope.row.platform === 'ios'">ios</el-tag>
<el-tag type="primary" v-else>android</el-tag>
</template>
</el-table-column>
<el-table-column label="版本号" sortable align="center" prop="versionCode" />
<el-table-column label="版本名称" sortable align="center" prop="versionName" />
<el-table-column label="最低支持版本" sortable align="center" prop="minVersionName" />
<el-table-column label="下载地址" align="center" prop="downloadUrl" />
<el-table-column label="更新日志" align="center" prop="releaseNotes" />
<el-table-column label="停用/启用" align="center" prop="status">
<template #default="scope">
<el-switch
@change="(val: string) => switchVersion(scope.row.id, val)"
v-model="scope.row.status"
active-value="1"
inactive-value="0"
></el-switch>
</template>
</el-table-column>
<el-table-column label="上传时间" align="center" prop="createTime" />
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
</el-card>
<!-- 添加或修改对话框 -->
<el-dialog :title="dialog.title" v-model="dialog.visible" width="650px" append-to-body>
<el-form ref="versionFormRef" :model="form" :rules="rules" label-width="130px">
<el-form-item label="App端" prop="channel">
<el-select @change="handleGetVersionlast" v-model="form.channel" placeholder="请选择">
<el-option label="花开管家App" value="butler"></el-option>
<el-option label="花开物业App" value="resident"></el-option>
</el-select>
</el-form-item>
<el-form-item label="App类型" prop="platform">
<el-radio-group @change="handleChangePlatform" v-model="form.platform">
<el-radio :value="appType.android">Android</el-radio>
<el-radio :value="appType.ios">ios</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="版本名称" prop="versionName">
<el-input v-model="form.versionName" placeholder="请输入版本名称例如:1.2.0" />
</el-form-item>
<el-form-item label="最低支持版本" prop="minVersionCode">
<el-select v-if="getlastVersionlist.length > 0" v-model="form.minVersionCode" placeholder="请输入最低支持版本">
<el-option v-for="(item, index) in getlastVersionlist" :key="index" :label="item.versionName" :value="item.versionCode"></el-option>
</el-select>
<el-select v-else v-model="form.minVersionCode" placeholder="请输入最低支持版本">
<el-option label="1.0.0" :value="1"></el-option>
</el-select>
</el-form-item>
<el-form-item label="更新日志" prop="releaseNotes">
<el-input v-model="form.releaseNotes" type="textarea" placeholder="请输入内容" />
</el-form-item>
<el-form-item label="低版本强制更新">
<div>
<el-switch
v-model="form.updateType"
:active-value="updateType.force"
active-text="开启"
:inactive-value="updateType.optional"
inactive-text="停止"
></el-switch>
<p class="tips">
<strong style="color: #000">配合最低支持版本使用</strong> 开启后: <br />低于最低版→启用强制(无取消,不更退出 APP);<br />高于最低版→普通弹窗可选取消。
</p>
</div>
</el-form-item>
<el-form-item label="更新地址" prop="downloadUrl" v-if="form.platform === appType.ios">
<el-input v-model="form.downloadUrl" placeholder="请输入App Store 链接" />
</el-form-item>
<div v-else-if="form.platform === appType.android">
<el-form-item label="更新类型">
<el-radio-group v-model="form.method">
<el-radio-button :value="updatePackageType.apk">整包更新(apk)</el-radio-button>
<el-radio-button :value="updatePackageType.wgt">热更新(wgt)</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="上传安装包地址" prop="downloadUrl">
<el-input v-model="form.downloadUrl" placeholder="请输入更新地址" />
</el-form-item>
</div>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
<el-button @click="cancel">取 消</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup name="Version" lang="ts">
import { listVersion, addVersion, getPastVersion, switchVersion } from '@/api/system/version/index';
import { VersionVO, VersionQuery, VersionForm } from '@/api/system/version/type';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const versionList = ref<VersionVO[]>([]);
const buttonLoading = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const queryFormRef = ref<ElFormInstance>();
const versionFormRef = ref<ElFormInstance>();
const dialog = reactive<DialogOption>({
visible: false,
title: ''
});
const initFormData: VersionForm = {
id: undefined,
platform: 'android',
versionCode: undefined,
versionName: undefined,
minVersionCode: '1.0.0',
updateType: undefined,
method: 'apk',
downloadUrl: undefined,
releaseNotes: undefined,
fileSize: undefined,
status: undefined,
channel: undefined
};
const data = reactive<PageData<VersionForm, VersionQuery>>({
form: { ...initFormData },
queryParams: {
pageNum: 1,
pageSize: 10,
platform: undefined,
versionCode: undefined,
versionName: undefined,
minVersionCode: undefined,
updateType: undefined,
downloadUrl: undefined,
releaseNotes: undefined,
fileSize: undefined,
status: undefined,
channel: undefined
},
rules: {
channel: [{ required: true, message: 'App应用不能为空', trigger: 'blur' }],
platform: [{ required: true, message: 'App类型不能为空', trigger: 'blur' }],
versionCode: [{ required: true, message: '版本号不能为空', trigger: 'blur' }],
versionName: [{ required: true, message: '版本名称不能为空', trigger: 'blur' }],
downloadUrl: [{ required: true, message: '安装包地址不能为空', trigger: 'blur' }]
}
});
const { queryParams, form, rules } = toRefs(data);
enum appType {
/** ios */
ios = 'ios',
/** android */
android = 'android'
}
/** 更新包类型 */
enum updatePackageType {
/** 整包更新 */
apk = 'apk',
/** 热更新 */
wgt = 'wgt'
}
enum updateType {
/** 强制更新 */
force = '0',
/** 可选更新 */
optional = '1'
}
const getlastVersionlist = ref([]);
/**
* 判断当前版本是否需要更新到最新版本。
* 比较逻辑为:如果当前版本号小于或等于最新版本号,则认为需要更新。
*
* @param {string} current - 当前版本号字符串,格式为点分十进制(如 "1.2.3")
* @param {string} latest - 最新版本号字符串,格式为点分十进制(如 "1.2.4")
* @returns {boolean} 如果当前版本小于或等于最新版本,返回 true;否则返回 false
*/
function needUpdate(current, latest) {
// 将版本号字符串分割并转换为数字数组
const c = current.split('.').map(Number);
const l = latest.split('.').map(Number);
const max = Math.max(c.length, l.length);
// 逐段比较版本号,若当前段小于最新段则需更新,大于则无需更新
for (let i = 0; i < max; i++) {
const cv = c[i] || 0;
const lv = l[i] || 0;
if (cv <= lv) return true;
if (cv > lv) return false;
}
return false;
}
/** 查询【请填写功能名称】列表 */
const getList = async () => {
loading.value = true;
const res = await listVersion(queryParams.value);
versionList.value = res.rows;
total.value = res.total;
loading.value = false;
};
/** 取消按钮 */
const cancel = () => {
reset();
dialog.visible = false;
};
/** 表单重置 */
const reset = () => {
form.value = { ...initFormData };
versionFormRef.value?.resetFields();
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
getList();
};
/** 重置按钮操作 */
const resetQuery = () => {
form.value = { ...initFormData };
queryFormRef.value?.resetFields();
handleQuery();
};
/** 多选框选中数据 */
const handleSelectionChange = (selection: VersionVO[]) => {
ids.value = selection.map((item) => item.id);
single.value = selection.length != 1;
multiple.value = !selection.length;
};
/** 新增按钮操作 */
const handleAdd = () => {
reset();
dialog.visible = true;
dialog.title = '添加版本';
};
function handleChangePlatform() {
form.value.minVersionCode = '1.0.0';
form.value.updateType = updateType.optional;
form.value.method = updatePackageType.apk;
form.value.downloadUrl = '';
handleGetVersionlast();
}
function handleGetVersionlast() {
getPastVersion(form.value.platform, form.value.channel).then((res) => {
getlastVersionlist.value = res.data;
form.value.minVersionCode = getlastVersionlist.value[getlastVersionlist.value.length - 1]
? getlastVersionlist.value[getlastVersionlist.value.length - 1].versionCode
: null;
});
}
/** 提交按钮 */
const submitForm = () => {
if (!form.value.minVersionCode) {
ElMessage.error('请选择最低支持版本');
return;
}
versionFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
await addVersion(form.value).finally(() => (buttonLoading.value = false));
proxy?.$modal.msgSuccess('操作成功');
dialog.visible = false;
await getList();
}
});
};
onMounted(() => {
getList();
});
</script>
<style lang="scss" scoped>
.el-table {
height: calc(100% - 80px);
}
.uploadFileBox {
width: 100px;
height: 100px;
border-radius: 4px 4px 4px 4px;
background-color: rgba(255, 255, 255, 1);
color: rgba(16, 16, 16, 1);
border: 1px solid #ccc;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
&:hover {
border: 1px solid #409eff;
color: #409eff;
}
}
.tips {
color: #ccc;
font-size: 12px;
}
</style>