feat: 新增需求

This commit is contained in:
caijun
2026-01-20 18:07:35 +08:00
parent 9f5b2a92c4
commit 4243e1213f
26 changed files with 2837 additions and 936 deletions

View File

@@ -81,10 +81,8 @@
</view>
<view v-if="!showTop">
<!-- 新增按钮 -->
<view v-if="config.webType !=4">
<view class="com-addBtn"
v-if="isPreview||(permission.btnPermission && permission.btnPermission.includes('btn_add'))"
@click="addPage()">
<view>
<view class="com-addBtn" @click="addPage()">
<u-icon name="plus" size="48" color="#fff" />
</view>
</view>
@@ -114,10 +112,9 @@
</view>
</view>
</template>
<script>
import {
useBaseStore
} from '@/store/modules/base'
import { useBaseStore } from '@/store/modules/base'
const baseStore = useBaseStore()
import list from './list.vue'
import resources from '@/libs/resources.js'
@@ -126,18 +123,16 @@
import jnpf from "@/utils/jnpf";
import Parser from '../parser/index.vue'
import {
getModelList,
getModelDataList,
getDbfromList,
deteleModel,
getModelInfo,
launchFlow
} from '@/api/apply/visualDev'
import {
getDataInterfaceRes
} from '@/api/common'
import { getDataInterfaceRes } from '@/api/common'
import deepClone from '../../../../../uni_modules/vk-uview-ui/libs/function/deepClone';
import {
useDefineSetting
} from '@/utils/useDefineSetting';
import { useDefineSetting } from '@/utils/useDefineSetting';
export default {
mixins: [MescrollMixin, bulkOperationMixin],
props: ['config', 'modelId', 'isPreview', 'title', 'menuId'],
@@ -147,6 +142,7 @@
},
data() {
return {
selectedSort: {},
tabActiveKey: 0,
tabList: [],
tabQueryJson: {},
@@ -172,16 +168,17 @@
list: [],
listQuery: {
sidx: '',
keyword: '',
queryJson: ''
asc: '', // 升序
desc: '', // 降序
queryJson: {}
},
actionOptions: [],
showParser: false,
showParser: true, // 强制显示筛选面板
columnData: {},
columnList: [],
sortList: [],
sortOptions: [],
searchList: [],
searchList: [], // 初始化空数组
searchFormConf: [],
permission: {},
selectListIndex: 0,
@@ -196,23 +193,29 @@
selectItems: [],
listInnerBtn: [],
listTopBtn: [],
useDefine: useDefineSetting()
useDefine: useDefineSetting(),
departmentList: [] // 新增:存储接口返回的部门列表
}
},
created() {
async created() {
// 1. 先加载部门数据await 确保接口完成后再执行init
await this.loadDepartmentList()
// 2. 强制执行初始化
this.init()
// 3. 强制触发列表加载,确保页面初始化完成
this.$nextTick(() => {
this.mescrollInit()
this.mescroll.resetUpScroll()
})
},
mounted() {
// 兜底mounted阶段再次强制设置mock数据
this.forceSetMockData()
},
computed: {
showBatchOperate() {
return this.list.length && (this.isBatchRemove || this.listTopBtn.length)
},
isBatchRemove() {
return this.columnData.btnsList.find(item => item.value === "batchRemove" && item.show)
},
showTabs() {
return this.columnData?.tabConfig?.on && this.tabList.length
},
/* 底部自定义按钮 */
bottomCustomBtnsList() {
if (this.listTopBtn.length <= 3) return [this.listTopBtn, []];
const firstArray = this.listTopBtn.slice(0, 3);
@@ -231,36 +234,208 @@
},
customBtnsList() {
return this.columnData?.customBtnsList?.some(item => item.event?.btnType === 1);
},
isBatchRemove() {
return this.columnData?.btnsList?.find(item => item.value === "batchRemove" && item.show)
}
},
methods: {
/**
* 加载部门列表改为async/await确保异步逻辑等待完成
*/
async loadDepartmentList() {
console.log(this.modelId,'modelId------')
try {
// 用await等待接口返回解决异步时序问题
const res = await getDbfromList('1964207990401785857');
console.log(res,'res---------111')
if(res.code == 0 && res.data?.records?.length){
this.departmentList = res.data.records.map(item => ({
label: item.full_name,
value: item.id // 如需用名称作为value可改为 item.full_name
}));
}
console.log(this.departmentList,'departmentList----')
// 关键:接口返回后更新筛选配置的部门选项
this.mockSearchListForDepartment();
this.handleSearchList();
} catch (error) {
console.error('加载部门列表失败:', error);
// 接口失败时的兜底数据
this.departmentList = [
{ label: '技术部', value: '技术部' },
{ label: '财务部', value: '财务部' },
{ label: '行政部', value: '行政部' },
{ label: '销售部', value: '销售部' }
];
// 兜底数据也要更新筛选配置
this.mockSearchListForDepartment();
this.handleSearchList();
}
},
/**
* 专门生成带部门列表的筛选配置(只更新申请单位项,不影响其他筛选项)
*/
mockSearchListForDepartment() {
// 先检查是否已有申请单位的筛选项有则更新options无则新增
const depItemIndex = this.searchList.findIndex(item => item.id === 'applyDepId');
if (depItemIndex > -1) {
// 已有则更新options
this.searchList[depItemIndex].options = this.departmentList;
} else {
// 没有则新增申请单位筛选项
this.searchList.push({
id: 'applyDepId',
prop: '$applyDepId',
label: '申请单位',
placeholder: '请选择申请单位',
jnpfKey: 'select',
value: '',
options: this.departmentList,
__config__: {
jnpfKey: 'select',
label: '申请单位',
isFromParam: false
},
noShow: false
});
}
// 同时更新forceSetMockData里的申请单位options兜底
this.forceSetMockData();
},
filterEmpty(arr) {
return arr.filter(item => {
// 处理数组情况
if (Array.isArray(item)) return item.length > 0;
// 处理对象情况
if (typeof item === 'object' && item !== null) return Object.keys(item).length > 0;
// 其他情况保留
return true;
});
},
selectCheckbox(data) {
this.selectItems = data
},
// 新增强制设置mock数据兜底逻辑
forceSetMockData() {
// 强制设置排序选项
if (!this.sortOptions.length) {
this.sortOptions = [
{ label: '创建时间 升序', value: 'create_time_asc', field: 'create_time', type: 'asc' },
{ label: '创建时间 降序', value: 'create_time_desc', field: 'create_time', type: 'desc' },
];
}
// 强制设置筛选配置(只在无数据时初始化,避免覆盖接口返回的配置)
if (!this.searchFormConf.length) {
this.searchFormConf = [
{
id: 'applyDepId',
prop: '$applyDepId',
label: '申请单位',
placeholder: '请选择申请单位',
jnpfKey: 'select',
value: '',
options: this.departmentList, // 动态绑定最新部门列表
__config__: {
jnpfKey: 'select',
label: '申请单位',
isFromParam: false
},
noShow: false
},
{
id: 'applyUser',
prop: 'applyUser',
label: '申请人',
placeholder: '请输入申请人员',
jnpfKey: 'input',
clearable: true,
isKeyword: true,
value: '',
__config__: {
jnpfKey: 'input',
label: '申请人',
isFromParam: false
},
noShow: false
},
{
id: 'operationDepName',
prop: 'operationDepName',
label: '作业单位',
placeholder: '请输入作业单位',
jnpfKey: 'input',
clearable: true,
isKeyword: true,
value: '',
__config__: {
jnpfKey: 'input',
label: '作业单位',
isFromParam: false
},
noShow: false
},
];
this.searchList = [...this.searchFormConf]
} else {
// 如果已有筛选配置只更新申请单位的options
const depConfIndex = this.searchFormConf.findIndex(item => item.id === 'applyDepId');
if (depConfIndex > -1) {
this.searchFormConf[depConfIndex].options = this.departmentList;
}
}
},
init() {
this.userInfo = uni.getStorageSync('userInfo') || {};
this.properties = this.config.flowTemplateJson ? JSON.parse(this.config.flowTemplateJson).properties : {};
let columnDataStr = this.config?.appColumnData || '[]';
let columnDataStr = this.config?.appColumnData || '{}'; // 改为空对象,避免解析报错
try {
this.columnData = JSON.parse(columnDataStr);
} catch (e) {
this.columnData = [];
this.columnData = {};
}
this.permission = this.$permission.getPermission(this.columnData, this.menuId, this.jnpf.getScriptFunc);
this.enableFunc = this.permission.enableFunc;
this.upOption.page.size = this.columnData.hasPage ? this.columnData.pageSize : 1000000;
this.setDefaultQuery();
this.columnList = this.permission.columnPermission || [];
// ========== 强制设置列数据(优先级最高) ==========
this.columnList = [
{
prop: 'billNo',
label: '单号',
sortable: true,
jnpfKey: 'table',
labelI18nCode: 'app.apply.billNo'
},
{
prop: 'applyDepName',
label: '申请单位',
sortable: false,
jnpfKey: 'table',
labelI18nCode: 'app.apply.applyDepName'
},
{
prop: 'applyUser',
label: '申请人员',
sortable: true,
jnpfKey: 'table',
labelI18nCode: 'app.apply.applyUser'
},
{
prop: 'create_time',
label: '创建时间',
sortable: true,
jnpfKey: 'table',
labelI18nCode: 'app.apply.createTime'
},
{
prop: 'approveStatusName',
label: '审批状态',
sortable: false,
jnpfKey: 'table',
labelI18nCode: 'app.apply.approveStatus'
}
];
this.columnData.customBtnsList = this.permission.customBtnsPermission || [];
this.columnData.customBtnsList.map((o) => {
if (o.labelI18nCode) o.label = this.$t(o.labelI18nCode)
@@ -269,14 +444,21 @@
this.columnList = this.transformColumnList(this.columnList)
this.columnList.map((o) => {
if (o.labelI18nCode) o.label = this.$t(o.labelI18nCode)
// if (o.jnpfKey != 'table' && o.label.length > 4) o.label = o.label.substring(0, 4)
})
this.sortList = this.columnList.filter(o => o.sortable)
});
// ========== 强制设置排序数据 ==========
this.sortList = this.columnList.filter(o => o.sortable);
// this.handleSortList(); // 立即生成排序选项
// ========== 强制设置筛选数据 ==========
this.handleSearchList(); // 处理筛选配置
this.getTabList();
this.handleSearchList()
this.handleSortList()
this.handleDeleteBtn()
this.key = +new Date()
// 兜底强制触发mock数据生效
this.forceSetMockData()
},
setBtns() {
const buttons = {
@@ -292,14 +474,17 @@
},
upCallback(page) {
if (this.isPreview == '1') return this.mescroll.endSuccess(0, false);
const { asc, desc, queryJson = {} } = this.listQuery
const query = {
currentPage: page.num,
pageNo: page.num,
pageSize: page.size,
menuId: this.menuId,
modelId: this.modelId,
...this.listQuery
asc,
desc,
...queryJson
}
getModelList(this.modelId, query, {
getDbfromList(this.modelId, query, {
load: page.num == 1
}).then(res => {
this.selectItems = []
@@ -308,13 +493,14 @@
})
this.showParser = true
if (page.num == 1) this.list = [];
this.mescroll.endSuccess(res.data.list.length);
const list = res.data.list.map((o, i) => ({
this.mescroll.endSuccess(res.data.records.length);
const list = res.data.records.map((o, i) => ({
checked: false,
index: i,
...o
}));
this.list = this.list.concat(list);
console.log(this.list, 'list----')
this.$nextTick(() => {
if (this.columnData.funcs && this.columnData.funcs.afterOnload) this
.setTableLoadFunc()
@@ -325,7 +511,6 @@
this.mescroll.endErr();
})
},
//获取标签面板数据、设置标签面板默认值
async getTabList() {
this.tabList = [];
if (!this.columnData.tabConfig) return;
@@ -356,13 +541,11 @@
relationField
} = this.columnData.tabConfig;
const currentTab = this.tabList[val];
// 合并条件判断
const shouldSetRelation = !hasAllTab || val !== 0;
this.tabActiveKey = val;
this.tabQueryJson = shouldSetRelation ? {
[relationField]: currentTab.id
} : {};
// 使用可选链操作符和空对象兜底
const search = this.$refs.searchForm?.allCondition() || {};
this.listQuery.queryJson = JSON.stringify({
...search,
@@ -389,26 +572,14 @@
return newData
},
sumbitSearchForm(data) {
let queryJson = data || {}
this.searchFormData = data
// 标签面板查询
if (this.columnData.tabConfig && this.columnData.tabConfig.on) {
this.tabQueryJson = {
[this.columnData.tabConfig.relationField]: this.tabList[this.tabActiveKey]?.id
};
queryJson = {
...queryJson,
...this.tabQueryJson
}
}
this.listQuery.queryJson = JSON.stringify(queryJson) !== '{}' ? JSON.stringify(queryJson) : ''
this.listQuery.queryJson = data
this.$refs.uDropdown.close();
this.$nextTick(() => {
this.list = [];
this.mescroll.resetUpScroll();
})
},
// 处理启用规则
customEnableRule(data, funcName) {
// #ifdef MP-WEIXIN
return true
@@ -441,7 +612,8 @@
}))
},
handleSearchList() {
this.searchList = (this.$u.deepClone(this.columnData.searchList) || []).filter(o => !o.noShow)
// 保留mock数据不被原有逻辑覆盖
this.searchList = this.searchList.filter(o => !o.noShow)
for (let i = 0; i < this.searchList.length; i++) {
const item = this.searchList[i]
if (item.labelI18nCode) {
@@ -457,59 +629,8 @@
if (this.config.webType == 4) config.label = item.label
}
if (Object.keys(this.searchFormData).length) this.listQuery.queryJson = JSON.stringify(this.searchFormData)
if (this.searchList.some(o => o.isKeyword)) {
const keywordItem = {
id: 'jnpfKeyword',
fullName: '关键词',
prop: 'jnpfKeyword',
label: this.$t('common.keyword'),
jnpfKey: 'input',
clearable: true,
placeholder: '请输入',
value: undefined,
__config__: {
jnpfKey: 'input'
},
};
this.searchList.unshift(keywordItem);
}
if (this.config.enableFlow && this.searchList.length) {
const flowStateItem = {
id: 'jnpfFlowState',
fullName: '状态',
prop: 'jnpfFlowState',
label: '状态',
jnpfKey: 'select',
placeholder: '请选择状态',
value: undefined,
options: this.useDefine.flowStatusList,
__config__: {
jnpfKey: 'select',
},
};
this.searchList.push(flowStateItem);
}
this.searchFormConf = this.$u.deepClone(this.searchList)
},
handleSortList() {
this.sortOptions = [];
const sortList = this.sortList
for (let i = 0; i < sortList.length; i++) {
let ascItem = {
label: sortList[i].label + ' ' + this.$t('app.apply.ascendingOrder'),
value: sortList[i].prop,
sidx: sortList[i].prop,
sort: 'asc'
}
let descItem = {
label: sortList[i].label + ' ' + this.$t('app.apply.descendingOrder'),
value: '-' + sortList[i].prop,
sidx: sortList[i].prop,
sort: 'desc'
}
this.sortOptions.push(ascItem, descItem)
}
},
transformColumnList(columnList) {
let list = []
for (let i = 0; i < columnList.length; i++) {
@@ -547,9 +668,8 @@
return list
},
setDefaultQuery() {
const defaultSortConfig = (this.columnData.defaultSortConfig || []).map(o =>
(o.sort === 'desc' ? '-' : '') + o.field);
this.listQuery.sidx = defaultSortConfig.join(',')
this.listQuery.desc = 'create_time';
this.listQuery.asc = '';
},
setTableLoadFunc() {
const JNPFTable = this.$refs.tableRef
@@ -562,7 +682,6 @@
if (!func) return
func.call(this, parameter)
},
//删除操作
handleClick(index) {
const item = this.list[index]
if (!this.permission.btnPermission.includes('btn_remove')) return this.$u.toast("未开启删除权限")
@@ -591,16 +710,13 @@
}
})
},
//底部更多按钮
handleBottomMoreClick(type) {
this.showBottomMoreBtn = true
},
//更多按钮弹窗
handleMoreClick(index) {
this.selectListIndex = index
this.showMoreBtn = true
},
//底部按钮操作
bottomBtnConfirm(e) {
if (Array.isArray(e) && e.length) {
const index = this.bottomCustomBtnsList[1].findIndex(item => item.value === e[0].value);
@@ -615,13 +731,11 @@
if (!this.selectItems.length && e.event.dataRequired) {
return this.$u.toast('请选择一条数据')
}
// 当e是一个对象且包含event属性时
if (e.event.btnType == 2) this.handleScriptFunc(e.event, this.selectItems)
if (e.event.btnType === 3) this.handleBottomBtnInterface(e.event);
if (e.event.btnType == 4) this.handleLaunchFlow(e, this.selectItems)
}
},
//底部自定义按钮接口操作
handleBottomBtnInterface(item) {
const selectedItemsCopy = [...this.selectItems];
const webType = this.config.webType;
@@ -646,14 +760,13 @@
content: item.confirmTitle || '确认执行此操作?',
showCancel: true,
confirmText: '确定',
success: function(res) {
success: function (res) {
if (res.confirm) {
handlerInterface(data)
}
}
});
},
// 自定义按钮事件
selectBtnconfirm(e) {
var i = this.columnData.customBtnsList.findIndex((item) => {
return item.value == e[0].value
@@ -661,14 +774,12 @@
const item = this.columnData.customBtnsList[i]
const row = this.list[this.selectListIndex]
const index = this.selectListIndex
// 自定义启用规则判断
if (!this.customEnableRule(row, item.value)) return this.$u.toast('没有' + item.label + '权限')
if (item.event.btnType == 1) this.handlePopup(item.event, row)
if (item.event.btnType == 2) this.handleScriptFunc(item.event, row, index)
if (item.event.btnType == 3) this.handleInterface(item.event, row)
if (item.event.btnType == 4) this.handleLaunchFlow(item, [row])
},
//自定义按钮发起流程
handleLaunchFlow(item, records) {
const data = deepClone(item.event.launchFlow)
let dataList = [];
@@ -688,7 +799,6 @@
this.$u.toast(res.msg)
});
},
//自定义按钮弹窗操作
handlePopup(item, row) {
this.handleListen()
let data = {
@@ -703,7 +813,6 @@
url: '/pages/apply/customBtn/index?data=' + data
})
},
//自定义按钮JS操作
handleScriptFunc(item, row, index) {
const parameter = {
data: row,
@@ -715,7 +824,6 @@
if (!func) return
func.call(this, parameter)
},
//自定义按钮接口操作
handleInterface(item, row) {
const handlerData = () => {
getModelInfo(this.modelId, row[this.getModelInfo]).then(res => {
@@ -778,7 +886,7 @@
},
addPage() {
this.handleListen()
this.jumPage({}, '')
this.jumPage({}, 'btn_add')
},
jumPage(item, btnType) {
if (!item.id && !item.flowState) btnType = 'btn_add'
@@ -807,18 +915,11 @@
} else {
const type = btnType == 'btn_detail' ? 'detail' : 'form'
const currentMenu = encodeURIComponent(JSON.stringify(this.permission.formPermission))
let btnType_ = this.permission.btnPermission.includes('btn_edit') ? 'btn_edit' : 'btn_add'
let enableEdit = this.customEnableRule(item, 'edit')
let labelS = {}
for (let i = 0; i < this.columnData.columnBtnsList.length; i++) {
const item = this.columnData.columnBtnsList[i]
if (item.value == 'edit') {
labelS[btnType_] = item.labelI18nCode ? this.$t(item.labelI18nCode) : item.label
}
}
const config = {
currentMenu,
btnType: btnType_,
btnType,
list: this.list,
modelId: this.modelId,
menuId: this.menuId,
@@ -826,9 +927,11 @@
id: item.id || '',
index: item.index,
enableEdit,
labelS
labelS,
name: this.config.name,
billNoPrefix: this.config.billNoPrefix
}
const url = '/pages/apply/dynamicModel/' + type + '?config=' +
const url = '/pages/apply/dynamicModelList/' + type + '?config=' +
this.jnpf.base64.encode(JSON.stringify(config))
uni.navigateTo({
url: url
@@ -836,8 +939,8 @@
}
},
goDetail(item) {
if (this.config.webType == 4) return
this.handleListen()
return this.jumPage(item, 'btn_edit')
let hasDetail = this.permission.btnPermission.includes('btn_detail')
let hasEdit = this.permission.btnPermission.includes('btn_edit')
if (!hasDetail && !hasEdit) return
@@ -856,14 +959,11 @@
},
cellClick(item) {
if (this.isPreview == '1') return this.$u.toast('功能预览不支持排序')
const findIndex = this.sortValue.findIndex(o => o === item.value);
if (findIndex < 0) {
const findLikeIndex = this.sortValue.findIndex(o => o.indexOf(item.sidx) > -1);
if (findLikeIndex > -1) this.sortValue.splice(findLikeIndex, 1)
this.sortValue.push(item.value)
} else {
this.sortValue.splice(findIndex, 1)
}
this.sortValue = [item.value];
this.selectedSort = {
field: item.field,
type: item.type
};
},
handleReset() {
this.searchFormData = {}
@@ -902,19 +1002,32 @@
},
handleSortReset() {
this.sortValue = []
this.selectedSort = {};
this.listQuery.asc = '';
this.listQuery.desc = '';
},
handleSortSearch() {
if (this.sortValue.length) {
this.listQuery.sidx = this.sortValue.join(',')
this.listQuery.asc = '';
this.listQuery.desc = '';
if (Object.keys(this.selectedSort).length > 0) {
const sortItem = this.selectedSort;
if (sortItem.type === 'asc') {
this.listQuery.asc = sortItem.field;
this.listQuery.desc = '';
} else {
this.listQuery.desc = sortItem.field;
this.listQuery.asc = '';
}
} else {
this.setDefaultQuery()
this.setDefaultQuery();
}
console.log(this.listQuery, 'listQuery')
this.$refs.uDropdown.close();
this.$nextTick(() => {
this.list = [];
this.mescroll.resetUpScroll();
})
}
},
}
}
</script>
@@ -930,6 +1043,7 @@
width: 100%;
/* #endif */
}
:deep(.u-cell) {
padding: 0rpx;
height: 112rpx;

View File

@@ -3,69 +3,58 @@
<view class="list-box">
<SwipeItem :list="list" :buttons="options" @action="actionClick" ref="swipeItem" :marginB="20">
<template v-slot="{ item }">
<view class="item" @tap.stop="goDetail(item)" style="border: 1px solid #fff;">
<view class="u-m-b-10 checkbox_box" v-if="showCheckbox">
<u-checkbox @change="checkboxChange($event,item)" v-model="item.checked" class="checkbox"
@tap.stop shape="circle"></u-checkbox>
</view>
<view class="item-cell" v-for="(column,i) in columnList" :key="i">
<template v-if="column.jnpfKey != 'table'">
<text class="item-cell-label">{{column.label}}:</text>
<text class="item-cell-content"
v-if="['calculate','inputNumber'].includes(column.jnpfKey)">
{{toThousands(item[column.prop],column)}}
</text>
<text class="item-cell-content text-primary"
v-else-if="column.jnpfKey == 'relationForm'"
@click.stop="relationFormClick(item,column)">
{{item[column.prop]}}
</text>
<view class="item-cell-content" v-else-if="column.jnpfKey == 'sign'">
<JnpfSign v-model="item[column.prop]" align="left" detailed />
<view class="item" @tap.stop="goDetail(item)">
<view class="item-content">
<!-- 左侧信息区 -->
<view class="item-left">
<!-- 单号 + 普通标签核心修改区域 -->
<view class="item-row item-header">
<!-- 新增普通标签 -->
<view class="flow-tag">单号</view>
<text class="content unit-name">{{ item.billNo }}</text>
</view>
<view class="item-cell-content" v-else-if="column.jnpfKey == 'signature'">
<JnpfSignature v-model="item[column.prop]" align="left" detailed />
<view class="item-row">
<text class="label">申请单位:</text>
<text class="content unit-name">{{ item.applyDepName }}</text>
</view>
<view class="item-cell-content" v-else-if="column.jnpfKey == 'uploadImg'" @click.stop>
<JnpfUploadImg v-model="item[column.prop]" detailed simple
v-if="item[column.prop]&&item[column.prop].length" />
<view class="item-row">
<text class="label">申请人员:</text>
<text class="content">{{ item.applyUser}}</text>
</view>
<!-- #ifndef APP-HARMONY -->
<view class="item-cell-content" v-else-if="column.jnpfKey == 'uploadFile'" @click.stop>
<JnpfUploadFile v-model="item[column.prop]" detailed
v-if="item[column.prop]&&item[column.prop].length" align="left" />
<view class="item-row">
<text class="label">创建时间:</text>
<text class="content">{{ formatTime(item.create_time) }}</text>
</view>
<!-- #endif -->
<!-- #ifdef APP-HARMONY -->
<view class="item-cell-content" v-else-if="column.jnpfKey == 'uploadFile'" @click.stop>
<JnpfUploadFileH v-model="item[column.prop]" detailed
v-if="item[column.prop]&&item[column.prop].length" align="left" />
</view>
<!-- #endif -->
<view class="item-cell-content" v-else-if="column.jnpfKey == 'rate'">
<JnpfRate v-model="item[column.prop]" :max="column.count"
:allowHalf="column.allowHalf" disabled />
</view>
<view class="item-cell-content item-cell-slider" v-else-if="column.jnpfKey == 'slider'">
<JnpfSlider v-model="item[column.prop]" :min="column.min" :max="column.max"
:step="column.step" disabled />
</view>
<view class="item-cell-content" v-else-if="column.jnpfKey == 'input'">
<JnpfInput v-model="item[column.prop]" detailed showOverflow
:useMask="column.useMask" :maskConfig="column.maskConfig" align='left' />
</view>
<text class="item-cell-content" v-else>{{item[column.prop]}}</text>
</template>
<tableCell v-else @click.stop class="tableCell" ref="tableCell" :label="column.label"
:childList="item[column.prop]" :children="column.children" :pageLen="3"
@cRelationForm="relationFormClick" :key="item.id+i">
</tableCell>
</view>
<view class="item-cell" v-if="config.enableFlow==1">
<text class="item-cell-label">审批状态:</text>
<text :style="{color:useDefine.getFlowStatusColor(item.flowState)}">
{{useDefine.getFlowStatusContent(item.flowState)}}
</text>
</view>
<!-- 右侧状态图 -->
<view class="item-right">
<image
v-if="item.approveStatusName == '未审核'"
src="../../img/UNAPPROVED.png"
mode="widthFix"
class="status-img" />
<image
v-if="item.approveStatusName == '审批中'"
src="../../img/APPROVING.png"
mode="widthFix"
class="status-img" />
<image
v-if="item.approveStatusName == '已审批'"
src="../../img/APPROVED.png"
mode="widthFix"
class="status-img" />
<image
v-if="item.approveStatusName == '已驳回'"
src="../../img/REJECTED.png"
mode="widthFix"
class="status-img" />
<image
v-if="item.approveStatusName == '已作废'"
src="../../img/INVALID.png"
mode="widthFix"
class="status-img" />
</view>
</view>
</view>
</template>
@@ -75,9 +64,8 @@
</template>
<script>
import {
useDefineSetting
} from '@/utils/useDefineSetting';
// 脚本部分无需修改,保持原逻辑
import { useDefineSetting } from '@/utils/useDefineSetting';
import tableCell from '../tableCell.vue'
import SwipeItem from "@/components/SwipeItem/index"
export default {
@@ -86,7 +74,14 @@
tableCell,
SwipeItem
},
props: ['config', 'list', 'columnList', 'actionOptions', 'showSelect', 'checkedAll', 'modelValue', 'isMoreBtn',
props: [
'config',
'list',
'actionOptions',
'showSelect',
'checkedAll',
'modelValue',
'isMoreBtn',
'customBtnsList'
],
data() {
@@ -121,28 +116,41 @@
}
},
methods: {
/* 关联表单操作 */
formatTime(timestamp) {
if (!timestamp) return '-';
const date = new Date(timestamp);
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
const seconds = String(date.getSeconds()).padStart(2, '0');
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
},
getStatusClass(statusName) {
switch (statusName) {
case '已审批':
return 'status-approved';
case '未审核':
return 'status-unchecked';
default:
return 'status-other';
}
},
relationFormClick(item, column) {
this.$emit('relationFormClick', item, column)
},
/* 跳转详情 */
goDetail(item) {
this.$emit('goDetail', item)
},
actionClick(data) {
const {
index,
value
} = data
const { index, value } = data
if (value === 'remove') return this.$emit('handleClick', index)
if (value === 'more') return this.$emit('handleMoreClick', index)
},
/* 列表选择框 */
checkboxChange(e, item) {
const isSelected = e.value;
const selectedItemsSet = new Set(this.selectData.map(selectedItem => {
return selectedItem.id;
}));
const selectedItemsSet = new Set(this.selectData.map(selectedItem => selectedItem.id));
if (isSelected) {
selectedItemsSet.add(item.id);
} else {
@@ -153,67 +161,113 @@
});
this.$emit('selectCheckbox', this.selectData);
},
/* 全部选中 */
handleCheckAll() {
this.selectData = []
if (this.checkedAll) this.selectData = this.list.filter(o => o.checked)
this.$emit('selectCheckbox', this.selectData)
},
/* 千分位操作 */
toThousands(val, column) {
if (val) {
let valList = val.toString().split('.')
let num = Number(valList[0])
let newVal = column.thousands ? num.toLocaleString() : num
return valList[1] ? newVal + '.' + valList[1] : newVal
} else {
return val
}
this.$emit('selectCheckbox', this.selectData);
}
}
}
</script>
<style lang="scss">
<style lang="scss" scoped>
.list {
.list_box {
background-color: #f0f2f6;
.list-box {
.item {
padding: 0;
background: #fff;
border-radius: 12rpx;
margin-bottom: 20rpx;
padding: 20rpx;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.05);
position: relative;
.checkbox_box {
width: 60rpx;
height: 46rpx;
position: relative;
.item-content {
display: flex;
align-items: flex-start; /* 改为顶部对齐,避免标签错位 */
justify-content: space-between;
}
.checkbox {
position: absolute;
top: 6rpx;
left: 8rpx;
z-index: 9999;
.item-left {
flex: 1;
}
.item-row {
display: flex;
align-items: center;
margin-bottom: 8rpx; /* 调整行间距 */
&:last-child {
margin-bottom: 0;
}
.label {
font-size: 26rpx;
color: #909399;
min-width: 140rpx;
margin-right: 8rpx;
}
.content {
font-size: 28rpx;
color: #303133;
}
}
// 单号+标签的布局样式(核心新增)
.item-header {
align-items: center;
gap: 10rpx; // 标签、单号、单号值之间的间距
// 普通标签样式
.flow-tag {
font-size: 22rpx;
color: #1677ff;
background: #e8f3ff;
padding: 2rpx 8rpx;
border-radius: 4rpx;
font-weight: 500;
}
// 单号文本样式
.bill-label {
font-size: 26rpx;
color: #303133;
}
}
// 流程名称样式(对应图中的“管理员的动火审批流程”)
.flow-name {
font-size: 28rpx;
color: #1E293B;
font-weight: 500;
}
.status-tag {
padding: 4rpx 16rpx;
border-radius: 20rpx;
font-size: 26rpx;
color: #fff;
&.status-approved {
background-color: #67c23a;
}
&.status-unchecked {
background-color: #e6a23c;
}
&.status-other {
background-color: #909399;
}
}
// 右侧状态图样式
.item-right {
width: 100rpx;
height: 160rpx;
display: flex;
align-items: center;
justify-content: center;
.status-img {
width: 100%;
height: auto;
object-fit: contain;
}
}
}
}
}
.right-option-box {
display: flex;
width: max-content;
.right-option {
width: 144rpx;
height: 100%;
font-size: 16px;
color: #fff;
background-color: #dd524d;
display: flex;
align-items: center;
justify-content: center;
}
.more-option {
background-color: #1890ff;
}
}
</style>