明道云视图插件,复杂表格效果制作,VUE3开发
iamdu2025-01-22 17:41:51明道云 浏览: 2054
<template>
<div class="app-con">
<div class="brand">
<div class="logo">
<img :src="icon" />
<div class="bg"></div>
</div>
<div class="hello">{{ title }}</div>
<div style="width: 1800px;height: auto; margin: 10px auto;">
<div class="records-count">
{{env.numeric}}当前视图共条
<b>{{ typeof count === "undefined" ? "?" : count }}</b> 记录{{ total }}
</div>
<!--emelent-plus表格-->
<el-table :data="currentPageData" border style="width: 100%; margin: 50px auto;" @row-click="openDetailinfo">
<el-table-column
v-for="field in selectedFields"
:key="field"
:prop="field"
:label="getFieldName(field)"
:width="180"
>
<template #default="scope">
<span>{{ getDisplayValue(scope.row[field], field) }}</span>
</template>
</el-table-column>
<!-- <el-table-column label="操作" width="180">
<template #default="scope">
<el-button @click="openDetailinfo(scope.row)">查看详情</el-button>
</template>
</el-table-column> -->
</el-table>
<!-- 表格 -->
<!--自定义设计表格-->
<table class="diyTable">
<thead>
<tr>
<th rowspan="2">三方单号</th>
<th rowspan="2">渠道平台</th>
<th rowspan="2">状态</th>
<th rowspan="2">下单时间</th>
<th colspan="4">订单明细</th>
<th rowspan="2">价格合计</th>
<th colspan="3">客户信息</th>
</tr>
<tr class="sub-head">
<th>商品</th>
<th>数量</th>
<th>单价</th>
<th>小计</th>
<th>姓名</th>
<th>年龄</th>
<th>手机</th>
</tr>
</thead>
<tbody>
<tr v-for="(item, index) in DiyTableData" :key="index">
<td>{{ item.orderNum }}</td>
<td>{{ item.qudao }}</td>
<td>{{ item.status }}</td>
<td>{{ item.orderTime }}</td>
<td colspan="4" class="td-sub">
<table class="sub-table">
<tbody>
<tr v-for="(subItem, subIndex) in item.subTableData" :key="subIndex" class="sub-head">
<td>{{ subItem.product }}</td>
<td>{{ subItem.quantity }}</td>
<td>{{ subItem.price }}</td>
<td>{{ subItem.subtotal }}</td>
</tr>
</tbody>
</table>
</td>
<td>{{ item.totalPrice }}</td>
<td colspan="3" class="td-sub">
<!--子表格2-->
<table class="sub-table">
<tbody>
<tr v-for="(subItem, subIndex) in item.CuTableData" :key="subIndex" class="sub-head">
<td>{{ subItem.user }}</td>
<td>{{ subItem.age }}</td>
<td>{{ subItem.phone }}</td>
</tr>
</tbody>
</table>
<!--子表格2END-->
</td>
</tr>
</tbody>
</table>
<div style=" margin: 50px;"></div>
<!--自定义设计表格END-->
<!--多级标头表格-->
<el-table :data="TableData" style="width: 100%">
<el-table-column prop="date" label="Date" width="150" />
<el-table-column label="Delivery Info">
<el-table-column prop="name" label="Name" width="120" />
<el-table-column label="Address Info">
<el-table-column prop="state" label="State" width="120" />
<el-table-column prop="city" label="City" width="120" />
<el-table-column prop="address" label="Address" />
<el-table-column prop="zip" label="Zip" width="120" />
</el-table-column>
</el-table-column>
</el-table>
<!--多级标头表格END-->
<el-pagination
background
layout="prev, pager, next"
:page-size="pageSize"
:total="total"
@current-change="handlePageChange"
/>
<div style="margin: 50px;"></div>
<!--时间线-->
<el-timeline style="max-width: 600px">
<!-- <el-timeline-item
v-for="(item, index) in timelineData"
:key="index"
:timestamp="item.timestamp"
>
{{ item.content }}
</el-timeline-item> -->
<el-timeline-item
v-for="(item, index) in timelineData"
:key="index"
:timestamp="item.timestamp"
placement="top"
>
<el-card>
<h4>{{ item.timestamp }}</h4>
<p>{{ item.content }}</p>
</el-card>
</el-timeline-item>
</el-timeline>
<!--时间线END-->
<div style="margin: 50px;"></div>
<el-button color="#626aef" :dark="isDark" @click="addNewRecord">新建记录</el-button>
<el-button color="#626aef" :dark="isDark" @click="openNewRecord">打开记录</el-button>
<el-button color="#626aef" :dark="isDark" @click="selectNewRecord">选择记录</el-button>
<el-button color="#626aef" :dark="isDark" @click="selectUser">选择人员</el-button>
<!---最近十条数据STAT-->
<div>
<table>
<thead>
<tr>
<th>序号</th>
<!-- 根据选择的字段动态生成表头 -->
<th v-for="field in selectedFields" :key="field">{{ getFieldName(field) }}</th>
</tr>
</thead>
<tbody>
<tr v-for="(item, index) in recentRecords" :key="index" @click="openDetailPage(item)">
<td>{{ index + 1 }}</td>
<!-- 根据选择的字段动态显示数据 -->
<td v-for="field in selectedFields" :key="`${index}-${field}`">{{ item[field] }}</td>
</tr>
</tbody>
</table>
</div>
<!--最近十条数据END-->
</div>
</div>
<div class="playground">
<div class="con">
<div class="block">
<div class="header">env 映射信息</div>
<div class="content env">
{{ JSON.stringify(env, null, 2) }}
</div>
</div>
<div class="block">
<div class="header">config 视图信息</div>
<div class="content variables">
{{ JSON.stringify({ appId, worksheetId, viewId }, null, 2) }}
</div>
</div>
<CallMdFunctionVue :addLog="addLog" />
<Logs :logs="logs" />
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from "vue";
import { config, env, api, utils } from "mdye";
import CallMdFunctionVue from "./components/CallMdFunction.vue";
import Logs from "./components/Logs.vue";
import icon from "./icon.svg";
import { createApp } from 'vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import { ElTable, ElTableColumn, ElPagination } from 'element-plus';
import { Delete, Edit, Search, Share, Upload } from '@element-plus/icons-vue'
function reset() {
value1.value0 = Date.now() + 1000 * 60 * 60 * 24 * 2
}
const activeNames = ref(['1'])
const color1 = ref('#409EFF')
const color2 = ref()
const num = ref(1)
const handleChange = (value) => {
console.log(value)
}
//新建记录
function addNewRecord() {
utils
.openNewRecord({
worksheetId,
})
.then((row) => {
addLog("创建成功,新纪录 id 是" + row.rowid);
});
}
//打开记录
function openNewRecord() {
utils
.selectRecord({
relateSheetId: worksheetId,
})
.then((records) => {
utils
.openRecordInfo({
appId,
worksheetId,
recordId: records[0].rowid,
})
.then((updatedRow) => {
console.log({ updatedRow });
addLog("已打开记录 ");
});
});
}
//选择记录
function selectNewRecord() {
utils
.selectRecord({
relateSheetId: worksheetId,
multiple: true,
})
.then((records) => {
addLog("已选择记录 " + records.map((r) => r.rowid));
});
}
//选择人员
async function selectUser() {
addLog("打开选择人员弹窗");
const users = await utils.selectUsers();
console.log(users);
addLog("已选择人员 " + users.map((u) => u.fullname));
}
const active = ref(0)
const next = () => {
if (active.value++ > 2) active.value = 0
}
const { appId, worksheetId, viewId } = config;
const value = ref(new Date());
const { getFilterRowsTotalNum } = api;
const title = ref("Hello Vue!");
const count = ref(undefined);
const logs = ref([]);
onMounted(() => {
addLog("hello world!");
loadRecords();
});
async function loadRecords() {
addLog("正在获取记录数量...");
count.value = await getFilterRowsTotalNum({ worksheetId, viewId });
addLog(`当前视图共${count.value}条记录`);
}
async function addLog(content) {
const time = new Date();
logs.value.push({
time,
timeStr: `[${[time.getHours(), time.getMinutes(), time.getSeconds()]
.map((num) => String(num).padStart(2, 0))
.join(":")}]`,
content,
});
}
// 用于存储最近十条数据
const recentRecords = ref([]);
// 用于存储选择的显示字段
const selectedFields = ref(env.showFields || []);
// 用于存储选择的显示字段
const sub = ref(env.sub || []);
console.log('envsub',sub)
// 用于存储字段ID到名称的映射
const fieldNameMap = ref({});
// 当前页码
const currentPage = ref(1);
// 每页显示的数据条数
const pageSize = ref(10);
// 数据总条数
const total = ref(0);
// 当前页的数据
const currentPageData = ref([]);
const timelineData = ref([]);
// 整理数据用于表格展示
const TableData = ref([]);
// 整理数据用于DiyTable表格展示
const DiyTableData = ref([]);
// 获取字段名称的函数
const getFieldName = (fieldId) => {
return fieldNameMap.value[fieldId] || fieldId;
};
// 判断是否为关联子表
const isSubTable = (field) => {
// 这里需要根据实际情况判断,例如检查字段配置信息
// console.log('field',config.controls[3].options )
// 假设 config.controls 包含了字段的信息,可以根据该信息判断
const control = config.controls.find(c => c.controlId === field);
return control && control.type === 29; // 请将 '关联子表类型' 替换为实际的关联子表类型标识
};
// 判断是否为单选字段
const isSingleSelect = (field) => {
const control = config.controls.find(c => c.controlId === field);
// 请根据实际情况修改以下判断条件,这里假设单选字段的类型是 11
return control && control.type === 11;
};
// 获取显示值
const getDisplayValue = (value, field) => {
if (isSubTable(field)) {
// console.log('运行到这里了',JSON.parse(value))
// 对于关联子表,根据子表数据结构和显示需求处理
if (Array.isArray(JSON.parse(value)) && JSON.parse(value).length > 0) {
let displayValue = '';
for (const subRecord of JSON.parse(value)) {
// 假设子表数据中的元素有一个名为 'name' 的属性用于显示
if (subRecord.name) {
displayValue += subRecord.name + ', ';
}
}
// 去除最后的逗号和空格
return displayValue.slice(0, -2);
}
return '';
} else if (isSingleSelect(field)) {
// 对于单选字段,根据其数据结构提取显示值,根据实际情况修改以下逻辑
// console.log('运行到这里了00single0',typeof value)
// console.log('运行到这里了,单选项', value)
if (typeof value === 'string' && value!== null) {
let data = config.controls[3].options;
for(let i=0; i<data.length; i++){
if(value.slice(2, -2) === data[i].key){
let value = data[i].value;
return value;
}
}
}
return '';
} else {
// 对于普通字段,直接返回值
return value;
}
};
// 获取子表数据的函数
const fetchSubTableData = async (rowId) => {
try {
const { worksheetId } = config;
const subTableControlId = '672ce60ae72ce9924f7aa377'; // 替换为实际的子表字段 controlId
const res = await api.getRowRelationRows({
worksheetId,
controlId: subTableControlId, // 子表字段的 controlId
rowId, // 主表记录的 rowid
});
console.log('获取子表数据成功:', res);
return res.data.map(subRecord => ({
product: subRecord['641bf5142c2835b432d02c82'], // 替换为实际的子表字段 controlId
quantity: subRecord['679052b2c43fee7e600fa51f'], // 替换为实际的子表字段 controlId
price: subRecord['679052b2c43fee7e600fa520'], // 替换为实际的子表字段 controlId
subtotal: subRecord['679052b2c43fee7e600fa521'], // 替换为实际的子表字段 controlId
}));
} catch (error) {
console.error('获取子表数据失败:', error);
return [];
}
};
// 获取客户明细子表数据的函数
const fetchCustomerTableData = async (rowId) => {
try {
const { worksheetId } = config;
const subTableControlId = '6790b20dc43fee7e6010b306'; // 替换为实际的子表字段 controlId
const res = await api.getRowRelationRows({
worksheetId,
controlId: subTableControlId, // 子表字段的 controlId
rowId, // 主表记录的 rowid
});
console.log('获取子表数据成功:', res);
return res.data.map(subRecord => ({
user: subRecord['6790b1d03445e2697128d853'], // 替换为实际的子表字段 controlId
age: subRecord['641d4951cf701ca4df6cde51'], // 替换为实际的子表字段 controlId
phone: subRecord['641d52b590531d40545fa5e4'], // 替换为实际的子表字段 controlId
}));
} catch (error) {
console.error('获取子表数据失败:', error);
return [];
}
};
// 获取数据的函数
const fetchData = async (page = 1, size = 10) => {
try {
const { worksheetId, viewId } = config;
const res = await api.getFilterRows({
worksheetId,
viewId,
pageIndex: page,
pageSize: size,
sortId: '创建时间字段的controlId', // 根据实际的创建时间字段ID修改
isAsc: false // 降序排列,以获取最近的数据
});
recentRecords.value = res.data;
total.value = res.count;
currentPageData.value = res.data;
console.log('获取数据成功:', res);
// 整理数据用于时间线展示
const newTimelineData = [];
res.data.forEach(record => {
// 假设记录中有 '时间字段名' 和 '内容字段名'
const timestamp = record['ctime'];
const content = record['642e7d5e485aef1653ec19b9'];
if (timestamp) {
newTimelineData.push({ timestamp, content });
}
});
// 假设从明道云获取的数据结构为 {明道云_date: '...', 明道云_name: '...', 明道云_state: '...', 明道云_city: '...', 明道云_address: '...', 明道云_zip: '...'}
const newTableData = [];
res.data.forEach(record => {
const date = record['ctime'];
const name = record['641bf4b4135e5a48af04a766'];
const state = record['641bfc8bf941415d0a2946d6'];
const city = record['641d6d48e3119c118082c01a'];
const address = record['642e7d5e485aef1653ec19b9'];
const zip = record['642e7d5e485aef1653ec19b8'];
newTableData.push({ date,name,state,city,address,zip});
});
// 收集所有的子表数据请求
const subTableDataPromises = res.data.map(record => fetchSubTableData(record.rowid));
// 等待所有子表数据请求完成
const subTableDataResults = await Promise.all(subTableDataPromises);
// 收集【会员信息】所有的子表数据请求
const CuTableDataPromises = res.data.map(record => fetchCustomerTableData(record.rowid));
// 等待【会员信息】所有子表数据请求完成
const CuTableDataResults = await Promise.all(CuTableDataPromises);
//DiyTableData数据结构;
const newDiyTableData = [];
res.data.forEach( (record, index)=> {
const orderNum = record['641bf4b4135e5a48af04a766'];
const qudao = record['641bf4d95236461cb7223ff5'];
const status = record['679052539a57a935b69c2f6a'];
const orderTime = record['679052539a57a935b69c2f6b'];
const totalPrice = record['6790ac776447b4f7cf0497d7']; //价格合计
newDiyTableData.push({orderNum,qudao,status,orderTime,totalPrice,subTableData: subTableDataResults[index],CuTableData:CuTableDataResults[index]});
});
console.log('新的数据',newDiyTableData)
TableData.value = newTableData;
DiyTableData.value = newDiyTableData;
timelineData.value = newTimelineData;
} catch (error) {
console.error('获取数据失败:', error);
}
};
// 获取config中的信息,实际使用时请从mdye.config获取
const useConfig = () => {
// 这里假设config是从mdye.config获取的对象
const config = {
worksheetId,
viewId
};
return config;
};
// 处理页码变化的函数
const handlePageChange = (newPage) => {
currentPage.value = newPage;
fetchData(newPage, pageSize.value);
};
onMounted(() => {
// 初始化字段ID到名称的映射
const controlMap = {};
config.controls.forEach(control => {
controlMap[control.controlId] = control.controlName;
});
fieldNameMap.value = controlMap;
fetchData();
});
// 打开详情页的函数
const openDetailPage = (item) => {
// 假设 item 包含唯一标识记录的字段 recordId,根据实际情况修改
const recordId = item.rowid;
console.log('打开详情页', recordId);
// 调用 openRecordInfo 打开详情信息,参考文档 https://help.mingdao.com/extensions/developer/view/#openrecordinfoparams
utils.openRecordInfo({
appId,
worksheetId,
viewId,
recordId:recordId
});
};
// 打开详情页的函数
const openDetailinfo = (item) => {
// 获取 row.id,假设 item 中存储的是 row 对象,根据实际情况修改
const rowId = item.rowid;
// 调用 openRecordInfo 打开详情信息,参考文档 https://help.mingdao.com/extensions/developer/view/#openrecordinfoparams
utils.openRecordInfo({
appId,
worksheetId,
viewId,
recordId: rowId
});
};
</script>
<style scoped>
table {
border-collapse: collapse;
height: 100%;
}
table,
th,
td {
border: 1px solid black;
padding: 0;
margin: 0;
}
.td-sub{padding: 0!important;}
table table {
border: none;
}
table table th,
table table td {
border: none;
}
/* 新增样式,设置子表格列宽与主表格对应列宽一致 */
.diyTable{table-layout: fixed; /* 固定表格布局 */}
#app .sub-head th,#app .sub-head td{ width: 120px!important;
height: auto;
margin: 0;
min-width: 120px; /* 最小宽度 */
max-width: 120px; /* 最大宽度 */
padding: 8px; overflow: hidden;}
.diyTable{
font-size: 14px;
}
.sub-table{border: 0;}
</style>
欢迎留下你的看法
共 0 条评论