Browse Source

fix: 长按移动项目改变层级关系

test2
xuesinan 3 years ago
parent
commit
20da3cfb3e
  1. 3
      CHANGELOG.md
  2. 180
      components/PrettyExchange/PrettyExchange - 副本.vue
  3. 188
      components/PrettyExchange/PrettyExchange.vue
  4. 693
      components/PrettyExchange/PrettyExchange222.vue
  5. 2
      components/Projects/ProjectItem.vue
  6. 1
      components/Projects/Projects.vue
  7. 2
      manifest.json
  8. 1
      uni_modules/vk-uview-ui/components/u-parse/libs/MpHtmlParser.js

3
CHANGELOG.md

@ -1,4 +1,4 @@
# 1.0.0 (2022-04-01)
# 1.0.0 (2022-04-06)
### 🌟 新功能
范围|描述|commitId
@ -161,6 +161,7 @@
- | 修复app打开详情页失败的问题 | [ecb943e](https://101.201.226.163:50022/TALL/TALL-MUI-4/commits/ecb943e)
- | 修复bug | [a55d08e](https://101.201.226.163:50022/TALL/TALL-MUI-4/commits/a55d08e)
- | 修复p-deliver报错taskRef的问题 | [880cf7c](https://101.201.226.163:50022/TALL/TALL-MUI-4/commits/880cf7c)
- | 长按拖动项目 | [7a05a0c](https://101.201.226.163:50022/TALL/TALL-MUI-4/commits/7a05a0c)
- | 子组件传参 | [489e218](https://101.201.226.163:50022/TALL/TALL-MUI-4/commits/489e218)
app.vue | 修复获取token报错的问题 | [9120d54](https://101.201.226.163:50022/TALL/TALL-MUI-4/commits/9120d54)
createTask | 修复createTask v-model的问题 | [b20d3f0](https://101.201.226.163:50022/TALL/TALL-MUI-4/commits/b20d3f0)

180
components/PrettyExchange/PrettyExchange - 副本.vue

@ -1,54 +1,42 @@
<template>
<view>
<scroll-view scroll-y="true">
<view v-if="!data.changeEvent">
<view :id="'cu-' + index" :key="item.id" class="cu-item flex-col" v-for="(item, index) in data.itemList">
<ProjectItem
class="w-full"
:index="index"
:item="item"
:menuList="data.menuList"
@setData="setData"
@openSubProject="openSubProject"
/>
</view>
</view>
<!-- 点击排序之后的效果 -->
<view v-else>
<view>
<view
:id="'cu-' + index"
:key="index"
class="cu-item flex-col"
v-for="(item, index) in data.itemList"
:key="item.id"
:style="{ 'background-color': item.color }"
@touchend="stops($event, index)"
@touchmove.stop.prevent="move"
@touchstart="start($event, index)"
class="cu-item flex-col"
v-for="(item, index) in data.itemList"
>
<!-- <view class="border-100 bg-blue-500" v-if="item.showTopBorder"></view> -->
<!-- 内容区 -->
<!-- 父项目 -->
<view class="w-full">
<view class="w-full" :style="{background: item.styleColor}">
<!-- 有子项目 父项目 -->
<view class="flex items-center justify-between p-3">
<u-icon class="mover" name="https://www.tall.wiki/staticrec/drag.svg" size="48"></u-icon>
<u-icon @click="openMenu(item, index)" class="mover" name="https://www.tall.wiki/staticrec/drag.svg" size="48"></u-icon>
<view class="flex-1 px-3">
<view class="flex items-center mb-1">
<view @click="openProject(item)" class="flex-1 px-3">
<view class="flex items-center" :class="{'mb-1': index > 0}">
<view class="mr-2">{{ item.name }}</view>
<!-- 状态 TODO:-->
<view class="px-2 text-xs text-green-400 bg-green-100 rounded-full flex-shrink-0">进行中</view>
<view class="px-2 text-xs text-green-400 bg-green-100 rounded-full flex-shrink-0">{{item.status === 1 ? '进行中' : item.status === 2 ? '已结束' : item.status === 0 ? '未开始' : '暂停'}}</view>
</view>
<view class="flex items-center text-xs text-gray-400">
<view v-if="index > 0" class="flex items-center text-xs text-gray-400">
<view class="pr-2">{{ dayjs(+item.startTime).format('MM-DD HH:mm') }}</view>
<view class="pl-2">{{ dayjs(+item.endTime).format('MM-DD HH:mm') }}</view>
</view>
</view>
<!-- <view class="workbench-btn" v-if="index === 0" @click="toWorkbench">工作台</view> -->
<view class="workbench-btn" v-if="index === 0" @click="toWorkbench">工作台</view>
<view class="remind-box bg-red-500 text-white text-xs" v-if="item.remindNum">{{ item.remindNum > 99 ? '99+' : item.remindNum }}</view>
<!-- 箭头 -->
<view v-if="item.sonProjectList && item.sonProjectList.length">
@ -67,9 +55,8 @@
v-else
></u-icon>
</view>
<u-icon class="text-gray-400" name="arrow-right" size="14px" v-else></u-icon>
<u-icon @click="openProject(item)" class="text-gray-400" name="arrow-right" size="14px" v-else></u-icon>
</view>
<!-- 父项目 end -->
<!-- 子项目 -->
<view class="ml-8" v-if="item.show">
@ -78,14 +65,15 @@
:key="subIndex"
@touchend.stop.prevent="stops($event, index + '-' + subIndex, item.sonProjectList.length)"
@touchmove.stop.prevent="move($event, item.sonProjectList.length)"
@touchstart.stop.prevent="start($event, index + '-' + subIndex)"
@longpress.stop.prevent="start($event, index + '-' + subIndex)"
class="cu-item flex-col"
v-for="(subItem, subIndex) in item.sonProjectList"
>
<!-- <view :key="subItem.id" v-for="subItem in item.sonProjectList"> -->
<view class="flex items-center justify-between p-3 w-full">
<u-icon class="mover" name="https://www.tall.wiki/staticrec/drag.svg" size="48"></u-icon>
<u-icon @click="openMenu(subItem)" class="mover" name="https://www.tall.wiki/staticrec/drag.svg" size="48"></u-icon>
<view class="flex-1 px-3">
<view @click="openProject(subItem)" class="flex-1 px-3">
<view class="flex items-center">
<view class="mr-2">{{ subItem.name }}</view>
<!-- 状态 -->
@ -107,12 +95,11 @@
</view>
<!-- 箭头 -->
<u-icon class="text-gray-400" name="arrow-right" size="14px"></u-icon>
<u-icon @click="openProject(subItem)" class="text-gray-400" name="arrow-right" size="14px"></u-icon>
</view>
</view>
</view>
</view>
<!-- 内容区 end -->
<view class="border-100 bg-blue-500" v-if="item.showBorder"></view>
<view class="border-80 bg-blue-500" v-if="item.showSubBorder"></view>
@ -129,7 +116,7 @@
<!-- 移动悬浮 end -->
<!-- 项目操作面板 -->
<u-action-sheet :list="data.menuList" :tips="data.tips" @click="chooseAction" v-model="data.showMenu"></u-action-sheet>
<u-action-sheet :list="data.menuList" :tips="data.tips" @click="chooseAction" v-model="data.showMenu" :cancel-btn="false"></u-action-sheet>
</view>
</template>
@ -142,6 +129,7 @@ import ProjectItem from '@/components/Projects/ProjectItem.vue';
const store = useStore();
const projects = computed(() => store.state.project.projects);
const remindData = computed(() => store.state.socket.remindData);
const userId = computed(() => store.getters['user/userId']);
const data = reactive({
// itemTop: 0,
// itemLeft: 0,
@ -164,12 +152,13 @@ const data = reactive({
clickProject: {},
projectId: 0,
// menuList: [{ text: '' }, { text: '' }, { text: '' }, { text: '' }, { text: '' }],
menuList: [{ text: '导入' }, { text: '导出' }, { text: '删除' }, { text: '排序' }],
menuList: [{ text: '导入' }, { text: '导出' }, { text: '删除' }],
// show: false,
// border: 'border border-blue-500 shadow rounded-md',
// showBorder: false, //
showItemIndex: undefined,
isStartMove: 0, //
});
const emit = defineEmits(['changeHeight', 'change']);
@ -234,12 +223,12 @@ function getDate() {
.exec();
}
function setData(flag, project, tips) {
data.showMenu = flag;
data.projectId = project.id;
data.tips = tips;
data.clickProject = project;
}
// function setData(flag, project, tips) {
// data.showMenu = flag;
// data.projectId = project.id;
// data.tips = tips;
// data.clickProject = project;
// }
function chooseAction(e) {
const obj = {
@ -255,24 +244,24 @@ function chooseAction(e) {
//
function actionFun(obj) {
const action = data.menuList[obj.index].text;
if (action === '排序') {
data.changeEvent = true;
uni.$ui.showToast('请移动进行排序');
}
// if (action === '') {
// data.changeEvent = true;
// uni.$ui.showToast('');
// }
if (action === '删除') {
data.changeEvent = false;
// data.changeEvent = false;
delProject(obj.projectId, obj.url);
}
if (action === '导入') {
data.changeEvent = false;
// data.changeEvent = false;
store.commit('setDomain', obj.url);
importProject(obj.projectId, obj.projectName);
}
if (action === '导出') {
data.changeEvent = false;
// data.changeEvent = false;
exportProject(obj.projectId, obj.url);
}
@ -289,7 +278,9 @@ function isNumber(val) {
}
function start(e, index) {
console.log('开始');
console.log('开始', e);
data.isStartMove = 1;
setTimeout(() => {
getDate();
}, 300);
@ -347,11 +338,15 @@ function start(e, index) {
size: true,
},
res => {
data.moveTop = res.top;
data.moveLeft = res.left;
console.log('res', res)
if (res) {
data.moveTop = res.top;
data.moveLeft = res.left;
data.itemWidth = res.width;
data.subItemHeight = res.height;
}
data.moveItem = data.itemList[arr[0] - 0].sonProjectList[arr[1] - 0];
data.itemWidth = res.width;
data.subItemHeight = res.height;
},
)
.exec();
@ -359,6 +354,7 @@ function start(e, index) {
}
function move(e, length) {
if (!data.isStartMove) return false;
console.log('移动');
data.showMoveImage = true; //
const touch = e.touches[0];
@ -398,10 +394,12 @@ function move(e, length) {
}
function stops(e, index, length) {
console.log('结束', e, index, length);
console.log('结束', e, index);
data.isStartMove = 0;
const touch = e.changedTouches[0];
const lastIndex = findOverIndex(touch.pageY, length);
console.log('11111111111', data.itemList)
//
for (let i = 0; i < data.itemList.length; i++) {
//
@ -426,6 +424,7 @@ function stops(e, index, length) {
};
emit('change', options);
}
//
clearSet(i);
emit('change', data.itemList);
@ -444,8 +443,8 @@ function stops(e, index, length) {
} else {
const arr = index.split('-');
const Value = data.itemList[arr[0] - 0].sonProjectList[arr[1] - 0];
data.itemList.splice(i + 1, 0, Value);
data.itemList[arr[0] - 0].sonProjectList.splice([arr[1] - 0], 1);
data.itemList.splice(i + 1, 0, Value);
// const options = {
// id: Value.id,
// parentId: 0,
@ -457,6 +456,7 @@ function stops(e, index, length) {
};
emit('change', options);
}
//
clearSet(i);
emit('change', data.itemList);
@ -524,13 +524,16 @@ function stops(e, index, length) {
//
function clearSet(i) {
data.itemList[i].showBorder = false;
data.itemList[i].showSubBorder = false;
data.itemList[i].showTopBorder = false;
if (i < data.itemList.length) {
data.itemList[i].showBorder = false;
data.itemList[i].showSubBorder = false;
data.itemList[i].showTopBorder = false;
}
data.deltaLeft == 0;
data.showMoveImage = false;
data.setSubItem = false;
data.changeEvent = false;
// data.changeEvent = false;
data.showItemIndex = undefined;
}
@ -653,9 +656,35 @@ function exportProject(id, url) {
}
//
// function toWorkbench() {
// uni.navigateTo({ url: '/pages/workbench/workbench' });
// }
function toWorkbench() {
uni.navigateTo({ url: '/pages/workbench/workbench' });
}
//
function openProject(project) {
store.commit('task/clearTasks'); //
store.commit('task/clearRealTasks'); //
store.commit('socket/setCurrLocationTaskId', '');
store.commit('task/setAllTasks', []); //
store.commit('task/setUpNextPage', 1);
store.commit('task/setDownNextPage', 1);
store.commit('task/setTimeLineType', 1);
const { name, id, url, businessCode } = project;
uni.navigateTo({ url: `/pages/project/project?u=${userId.value}&p=${id}&pname=${name}&url=${encodeURIComponent(url)}&businessCode=${businessCode}` });
}
/**
* 弹出项目操作面板
*/
function openMenu(project, index) {
if (index === 0) return;
data.showMenu = true;
data.projectId = project.id;
data.tips.text = project.name;
data.clickProject = project;
// emit('setData', data.showMenu, project, data.tips);
}
</script>
<style lang="scss" scoped>
@ -667,22 +696,21 @@ function exportProject(id, url) {
}
.border-100 {
width: 92%;
height: 4rpx;
margin: 0 20rpx;
}
.border-80 {
width: 84%;
height: 2px;
margin-left: 30px;
height: 4rpx;
margin: 0 20rpx 0 90rpx;
}
.workbench-btn {
margin-right: 10px;
width: 80px;
height: 36px;
line-height: 36px;
border-radius: 18px;
height: 30px;
line-height: 30px;
border-radius: 15px;
overflow: hidden;
border: 1px solid #2b85e4;
background-color: #1890ff;
@ -690,4 +718,14 @@ function exportProject(id, url) {
color: #ffffff;
text-align: center;
}
.remind-box {
padding: 0 3px;
min-width: 16px;
height: 16px;
text-align: center;
line-height: 16px;
border-radius: 8px;
font-weight: 100;
}
</style>

188
components/PrettyExchange/PrettyExchange.vue

@ -13,11 +13,11 @@
@longpress="start($event, index)"
>
<!-- <view class="border-100 bg-blue-500" v-if="item.showTopBorder"></view> -->
<view class="w-full border-100 bg-blue-500" v-if="item.showTopBorder"></view>
<view class="w-full" :style="{background: item.styleColor}">
<!-- 有子项目 父项目 -->
<view class="flex items-center justify-between p-3">
<view class="h-65 flex items-center justify-between p-3">
<u-icon @click="openMenu(item, index)" class="mover" name="https://www.tall.wiki/staticrec/drag.svg" size="48"></u-icon>
<view @click="openProject(item)" class="flex-1 px-3">
@ -70,7 +70,7 @@
v-for="(subItem, subIndex) in item.sonProjectList"
>
<!-- <view :key="subItem.id" v-for="subItem in item.sonProjectList"> -->
<view class="flex items-center justify-between p-3 w-full">
<view class="h-65 flex items-center justify-between p-3 w-full">
<u-icon @click="openMenu(subItem)" class="mover" name="https://www.tall.wiki/staticrec/drag.svg" size="48"></u-icon>
<view @click="openProject(subItem)" class="flex-1 px-3">
@ -101,8 +101,8 @@
</view>
</view>
<view class="border-100 bg-blue-500" v-if="item.showBorder"></view>
<view class="border-80 bg-blue-500" v-if="item.showSubBorder"></view>
<view class="w-full border-100 bg-blue-500" v-if="item.showBorder"></view>
<view class="w-full border-80 bg-blue-500" v-if="item.showSubBorder"></view>
</view>
</view>
</scroll-view>
@ -133,19 +133,24 @@ const userId = computed(() => store.getters['user/userId']);
const data = reactive({
// itemTop: 0,
// itemLeft: 0,
itemHeight: 0, //
itemWidth: 0, //
subItemHeight: 0, //
showMoveImage: false,
moveItem: '', //
moveLeft: 0, //
moveTop: 0, //
begintop: 0, //
beginleft: 0, //
itemHeight: 0, //
itemWidth: 0, //
moveItem: '', //
moveLeft: 0, //
moveTop: 0, //
showMoveImage: false, //
// subItemHeight: 0, //
deltaLeft: 0,
deltaTop: 0,
beginleft: 0, //
begintop: 0, //
itemList: [], //
setSubItem: false, //
// setSubItem: false, //
changeEvent: false, //
showMenu: false,
tips: { text: '', color: '#909399', fontSize: 28 },
@ -159,6 +164,7 @@ const data = reactive({
// showBorder: false, //
showItemIndex: undefined,
isStartMove: 0, //
timer: null
});
const emit = defineEmits(['changeHeight', 'change']);
@ -273,21 +279,25 @@ function actionFun(obj) {
}
}
//
function isNumber(val) {
return val === +val;
}
function start(e, index) {
console.log('开始', e);
data.isStartMove = 1;
data.timer = setTimeout(() => {
data.isStartMove = 1;
// console.log('', e, index);
}, 1500);
setTimeout(() => {
getDate();
getDate(); //
}, 300);
// 1,2
if (isNumber(index)) {
//
data.setSubItem = false;
// data.setSubItem = false;
const query = uni
.createSelectorQuery()
.select(`#cu-${index}`)
@ -310,7 +320,7 @@ function start(e, index) {
} else {
//
const arr = index.split('-');
data.setSubItem = true;
// data.setSubItem = true;
const query = uni.createSelectorQuery();
query
@ -338,11 +348,14 @@ function start(e, index) {
size: true,
},
res => {
data.moveTop = res.top;
data.moveLeft = res.left;
if (res) {
data.moveTop = res.top;
data.moveLeft = res.left;
data.itemWidth = res.width;
// data.subItemHeight = res.height;
}
data.moveItem = data.itemList[arr[0] - 0].sonProjectList[arr[1] - 0];
data.itemWidth = res.width;
data.subItemHeight = res.height;
},
)
.exec();
@ -351,11 +364,11 @@ function start(e, index) {
function move(e, length) {
if (!data.isStartMove) return false;
console.log('移动');
// console.log('');
data.showMoveImage = true; //
const touch = e.touches[0];
if (data.deltaLeft == 0) {
//
//
data.deltaLeft = touch.pageX - data.moveLeft;
data.deltaTop = touch.pageY - data.moveTop;
}
@ -363,9 +376,10 @@ function move(e, length) {
data.moveTop = touch.pageY - data.deltaTop;
const lastIndex = findOverIndex(touch.pageY, length);
// 线
for (let i = 0; i < data.itemList.length; i++) {
if (data.moveLeft > 35) {
if (data.moveLeft > 35 && lastIndex > -1) {
data.itemList[i].showBorder = false;
data.itemList[i].showTopBorder = false;
if (i === lastIndex) {
@ -390,8 +404,9 @@ function move(e, length) {
}
function stops(e, index, length) {
console.log('结束');
// console.log('', e, index);
data.isStartMove = 0;
clearTimeout(data.timer);
const touch = e.changedTouches[0];
const lastIndex = findOverIndex(touch.pageY, length);
@ -400,119 +415,83 @@ function stops(e, index, length) {
for (let i = 0; i < data.itemList.length; i++) {
//
if (data.itemList[i].showTopBorder) {
if (isNumber(index)) {
const Value = data.itemList[index];
data.itemList.unshift(Value);
data.itemList.splice(index + 1, 1);
} else {
if (!isNumber(index)) {
//
const arr = index.split('-');
const Value = data.itemList[arr[0] - 0].sonProjectList[arr[1] - 0];
data.itemList.unshift(Value);
data.itemList[arr[0] - 0].sonProjectList.splice([arr[1] - 0], 1);
// const options = {
// id: Value.id,
// parentId: 0,
// };
const options = {
businessCode: Value.businessCode,
moveProjectId: Value.id,
targetProjectId: '',
};
emit('change', options);
} else {
//
emit('change', data.itemList);
}
//
clearSet(i);
emit('change', data.itemList);
return;
}
//
if (data.itemList[i].showBorder) {
if (isNumber(index)) {
const Value = data.itemList[index];
data.itemList.splice(i + 1, 0, Value);
if (i < index) {
data.itemList.splice(index + 1, 1);
} else {
data.itemList.splice(index, 1);
}
} else {
if (!isNumber(index)) {
//
const arr = index.split('-');
const Value = data.itemList[arr[0] - 0].sonProjectList[arr[1] - 0];
data.itemList[arr[0] - 0].sonProjectList.splice([arr[1] - 0], 1);
data.itemList.splice(i + 1, 0, Value);
// const options = {
// id: Value.id,
// parentId: 0,
// };
const options = {
businessCode: Value.businessCode,
moveProjectId: Value.id,
targetProjectId: '',
};
emit('change', options);
} else {
//
emit('change', data.itemList);
}
//
clearSet(i);
emit('change', data.itemList);
return;
}
//
if (data.itemList[i].showSubBorder) {
if (isNumber(index)) {
//
const Value = data.itemList[index];
if (data.itemList[lastIndex - 1].sonProjectList && data.itemList[lastIndex - 1].sonProjectList.length) {
data.itemList[lastIndex - 1].sonProjectList.push(Value);
let targetProjectId = '';
if (index === i) {
targetProjectId = data.itemList[i-1].id;
} else {
data.itemList[lastIndex].sonProjectList = [Value];
targetProjectId = data.itemList[i].id;
}
data.itemList.splice(index, 1);
//
clearSet(i);
// const options = {
// id: Value.id,
// parentId: data.itemList[lastIndex - 1].id,
// };
const options = {
businessCode: Value.businessCode,
moveProjectId: Value.id,
targetProjectId: data.itemList[lastIndex - 1].id,
targetProjectId: targetProjectId,
};
emit('change', options);
} else {
//
const arr = index.split('-');
const Value = data.itemList[arr[0] - 0].sonProjectList[arr[1] - 0];
if (data.itemList[lastIndex].sonProjectList && data.itemList[lastIndex].sonProjectList.length) {
data.itemList[lastIndex].sonProjectList.push(Value);
} else {
data.itemList[lastIndex].sonProjectList = [Value];
}
data.itemList[arr[0] - 0].sonProjectList.splice([arr[1] - 0], 1);
//
clearSet(i);
// const options = {
// id: Value.id,
// parentId: data.itemList[lastIndex].id,
// };
const options = {
businessCode: Value.businessCode,
moveProjectId: Value.id,
targetProjectId: data.itemList[lastIndex].id,
};
emit('change', options);
// const options1 = {
// id: Value.id,
// parentId: 0,
// };
const options1 = {
businessCode: Value.businessCode,
moveProjectId: Value.id,
targetProjectId: '',
};
emit('change', options1);
}
//
clearSet(i);
return;
}
}
@ -528,32 +507,37 @@ function clearSet(i) {
data.deltaLeft == 0;
data.showMoveImage = false;
data.setSubItem = false;
// data.setSubItem = false;
// data.changeEvent = false;
data.showItemIndex = undefined;
}
//
function findOverIndex(posY) {
//
const leng = data.itemList.length * data.itemHeight; //
if (posY < data.begintop) {
if (posY < data.begintop) { //
return -1;
}
for (let i = 0; i < data.itemList.length; i++) {
const begin = data.itemHeight * i + data.begintop;
const end = data.itemHeight * i + data.begintop + data.itemHeight;
const begin = 65 * i + data.begintop;
const end = data.begintop + 65 * i + data.itemHeight;
if (begin <= posY && end >= posY) {
return i;
}
}
if (posY > leng) {
//
let allNum = data.itemList.length;
data.itemList.forEach(item => {
if (item.show) {
allNum += item.sonProjectList.length;
}
})
const leng = allNum * 65; //
if (posY > (leng + data.begintop)) {
//
return data.itemList.length - 1;
}
if (posY < data.begintop) {
return 0;
}
}
//
@ -684,6 +668,10 @@ function openMenu(project, index) {
</script>
<style lang="scss" scoped>
.h-65 {
height: 65px;
}
.cu-item {
width: 100%;
display: flex;

693
components/PrettyExchange/PrettyExchange222.vue

@ -0,0 +1,693 @@
<template>
<view>
<scroll-view scroll-y="true">
<view v-if="!data.changeEvent">
<view :id="'cu-' + index" :key="item.id" class="cu-item flex-col" v-for="(item, index) in data.itemList">
<ProjectItem
class="w-full"
:index="index"
:item="item"
:menuList="data.menuList"
@setData="setData"
@openSubProject="openSubProject"
/>
</view>
</view>
<!-- 点击排序之后的效果 -->
<view v-else>
<view
:id="'cu-' + index"
:key="index"
:style="{ 'background-color': item.color }"
@touchend="stops($event, index)"
@touchmove.stop.prevent="move"
@touchstart="start($event, index)"
class="cu-item flex-col"
v-for="(item, index) in data.itemList"
>
<!-- <view class="border-100 bg-blue-500" v-if="item.showTopBorder"></view> -->
<!-- 内容区 -->
<!-- 父项目 -->
<view class="w-full">
<view class="flex items-center justify-between p-3">
<u-icon class="mover" name="https://www.tall.wiki/staticrec/drag.svg" size="48"></u-icon>
<view class="flex-1 px-3">
<view class="flex items-center mb-1">
<view class="mr-2">{{ item.name }}</view>
<!-- 状态 TODO:-->
<view class="px-2 text-xs text-green-400 bg-green-100 rounded-full flex-shrink-0">进行中</view>
</view>
<view class="flex items-center text-xs text-gray-400">
<view class="pr-2">{{ dayjs(+item.startTime).format('MM-DD HH:mm') }}</view>
<view class="pl-2">{{ dayjs(+item.endTime).format('MM-DD HH:mm') }}</view>
</view>
</view>
<!-- <view class="workbench-btn" v-if="index === 0" @click="toWorkbench">工作台</view> -->
<!-- 箭头 -->
<view v-if="item.sonProjectList && item.sonProjectList.length">
<u-icon
@click="openSubProject(item.sonProjectList.length, index)"
class="text-gray-400"
name="arrow-up"
size="14px"
v-if="item.show"
></u-icon>
<u-icon
@click="openSubProject(item.sonProjectList.length, index)"
class="text-gray-400"
name="arrow-down"
size="14px"
v-else
></u-icon>
</view>
<u-icon class="text-gray-400" name="arrow-right" size="14px" v-else></u-icon>
</view>
<!-- 父项目 end -->
<!-- 子项目 -->
<view class="ml-8" v-if="item.show">
<view
:id="'cu-' + index + '-' + subIndex"
:key="subIndex"
@touchend.stop.prevent="stops($event, index + '-' + subIndex, item.sonProjectList.length)"
@touchmove.stop.prevent="move($event, item.sonProjectList.length)"
@touchstart.stop.prevent="start($event, index + '-' + subIndex)"
class="cu-item flex-col"
v-for="(subItem, subIndex) in item.sonProjectList"
>
<view class="flex items-center justify-between p-3 w-full">
<u-icon class="mover" name="https://www.tall.wiki/staticrec/drag.svg" size="48"></u-icon>
<view class="flex-1 px-3">
<view class="flex items-center">
<view class="mr-2">{{ subItem.name }}</view>
<!-- 状态 -->
<view
:class="
subItem.status === 0
? 'text-blue-400 bg-blue-100'
: subItem.status === 1
? 'text-green-400 bg-green-100'
: subItem.status === 2
? 'text-red-400 bg-red-100'
: 'text-gray-400 bg-gray-100'
"
class="px-2 text-xs text-gray-400 bg-gray-100 rounded-full flex-shrink-0"
>
{{ subItem.status === 0 ? '未开始' : subItem.status === 1 ? '进行中' : subItem.status === 2 ? '暂停' : '已完成' }}
</view>
</view>
</view>
<!-- 箭头 -->
<u-icon class="text-gray-400" name="arrow-right" size="14px"></u-icon>
</view>
</view>
</view>
</view>
<!-- 内容区 end -->
<view class="border-100 bg-blue-500" v-if="item.showBorder"></view>
<view class="border-80 bg-blue-500" v-if="item.showSubBorder"></view>
</view>
</view>
</scroll-view>
<!-- 移动悬浮 begin -->
<view v-if="data.showMoveImage">
<view :style="{ left: data.moveLeft + 'px', top: data.moveTop + 'px' }" class="cu-item absolute">
<ProjectItem class="w-full" :item="data.moveItem" />
</view>
</view>
<!-- 移动悬浮 end -->
<!-- 项目操作面板 -->
<u-action-sheet :list="data.menuList" :tips="data.tips" @click="chooseAction" v-model="data.showMenu"></u-action-sheet>
</view>
</template>
<script setup>
import { reactive, onMounted, watchEffect, computed } from 'vue';
import { useStore } from 'vuex';
import dayjs from 'dayjs';
import ProjectItem from '@/components/Projects/ProjectItem.vue';
const store = useStore();
const projects = computed(() => store.state.project.projects);
const remindData = computed(() => store.state.socket.remindData);
const data = reactive({
// itemTop: 0,
// itemLeft: 0,
itemHeight: 0, //
itemWidth: 0, //
subItemHeight: 0, //
showMoveImage: false,
moveItem: '', //
moveLeft: 0, //
moveTop: 0, //
deltaLeft: 0,
deltaTop: 0,
beginleft: 0, //
begintop: 0, //
itemList: [], //
setSubItem: false, //
changeEvent: false, //
showMenu: false,
tips: { text: '', color: '#909399', fontSize: 28 },
clickProject: {},
projectId: 0,
// menuList: [{ text: '' }, { text: '' }, { text: '' }, { text: '' }, { text: '' }],
menuList: [{ text: '导入' }, { text: '导出' }, { text: '删除' }, { text: '排序' }],
// show: false,
// border: 'border border-blue-500 shadow rounded-md',
// showBorder: false, //
showItemIndex: undefined,
});
const emit = defineEmits(['changeHeight', 'change']);
//
watchEffect(() => {
if (projects.value) {
data.itemList = projects.value;
data.itemList.forEach(item => {
item.showBorder = false; //
item.showSubBorder = false; //
item.showTopBorder = false; //
item.remindNum = 0;
if (remindData.value) {
remindData.value.forEach(remind => {
const remind_data = JSON.parse(remind.data);
if (remind_data.data.projectId === item.id) {
item.remindNum++;
}
});
}
});
}
});
onMounted(() => {
data.itemList = projects.value;
data.itemList.forEach(item => {
item.showBorder = false; //
item.showSubBorder = false; //
item.showTopBorder = false; //
});
});
//
function openSubProject(length, index) {
store.commit('project/setProjectItemShow', { index, show: !data.itemList[index].show });
if (length && index) {
emit('changeHeight', length, index);
}
data.showItemIndex = index;
}
//
function getDate() {
const query = uni
.createSelectorQuery()
.select('#cu-0')
.fields(
{
id: true,
dataset: true,
rect: true,
size: true,
},
res => {
data.begintop = res.top;
data.beginleft = res.left;
},
)
.exec();
}
function setData(flag, project, tips) {
data.showMenu = flag;
data.projectId = project.id;
data.tips = tips;
data.clickProject = project;
}
function chooseAction(e) {
const obj = {
index: e,
projectId: data.projectId,
url: data.clickProject.url,
projectName: data.tips.text
};
// emit('chooseAction', data);
actionFun(obj);
}
//
function actionFun(obj) {
const action = data.menuList[obj.index].text;
if (action === '排序') {
data.changeEvent = true;
uni.$ui.showToast('请移动进行排序');
}
if (action === '删除') {
data.changeEvent = false;
delProject(obj.projectId, obj.url);
}
if (action === '导入') {
data.changeEvent = false;
store.commit('setDomain', obj.url);
importProject(obj.projectId, obj.projectName);
}
if (action === '导出') {
data.changeEvent = false;
exportProject(obj.projectId, obj.url);
}
if (data.showItemIndex !== undefined) {
store.commit('project/setProjectItemShow', {
index: data.showItemIndex,
show: true,
});
}
}
function isNumber(val) {
return val === +val;
}
function start(e, index) {
console.log('开始');
setTimeout(() => {
getDate();
}, 300);
if (isNumber(index)) {
//
data.setSubItem = false;
const query = uni
.createSelectorQuery()
.select(`#cu-${index}`)
.fields(
{
id: true,
dataset: true,
rect: true,
size: true,
},
res => {
data.moveTop = res.top;
data.moveLeft = res.left;
data.moveItem = data.itemList[index];
data.itemWidth = res.width;
data.itemHeight = res.height;
},
)
.exec();
} else {
//
const arr = index.split('-');
data.setSubItem = true;
const query = uni.createSelectorQuery();
query
.select(`#cu-${arr[0] - 0}`)
.fields(
{
id: true,
dataset: true,
rect: true,
size: true,
},
res => {
data.itemHeight = res.height;
},
)
.exec();
query
.select(`#cu-${index}`)
.fields(
{
id: true,
dataset: true,
rect: true,
size: true,
},
res => {
data.moveTop = res.top;
data.moveLeft = res.left;
data.moveItem = data.itemList[arr[0] - 0].sonProjectList[arr[1] - 0];
data.itemWidth = res.width;
data.subItemHeight = res.height;
},
)
.exec();
}
}
function move(e, length) {
console.log('移动');
data.showMoveImage = true; //
const touch = e.touches[0];
if (data.deltaLeft == 0) {
//
data.deltaLeft = touch.pageX - data.moveLeft;
data.deltaTop = touch.pageY - data.moveTop;
}
data.moveLeft = touch.pageX - data.deltaLeft;
data.moveTop = touch.pageY - data.deltaTop;
const lastIndex = findOverIndex(touch.pageY, length);
// 线
for (let i = 0; i < data.itemList.length; i++) {
if (data.moveLeft > 35) {
data.itemList[i].showBorder = false;
data.itemList[i].showTopBorder = false;
if (i === lastIndex) {
data.itemList[i].showSubBorder = true;
} else {
data.itemList[i].showSubBorder = false;
}
} else if (lastIndex === -1) {
data.itemList[0].showTopBorder = true;
data.itemList[i].showSubBorder = false;
data.itemList[i].showBorder = false;
} else {
data.itemList[i].showSubBorder = false;
data.itemList[i].showTopBorder = false;
if (i === lastIndex) {
data.itemList[i].showBorder = true;
} else {
data.itemList[i].showBorder = false;
}
}
}
}
function stops(e, index, length) {
console.log('结束', e, index, length);
const touch = e.changedTouches[0];
const lastIndex = findOverIndex(touch.pageY, length);
console.log('11111111111', data.itemList)
//
for (let i = 0; i < data.itemList.length; i++) {
//
if (data.itemList[i].showTopBorder) {
if (isNumber(index)) {
const Value = data.itemList[index];
data.itemList.unshift(Value);
data.itemList.splice(index + 1, 1);
} else {
const arr = index.split('-');
const Value = data.itemList[arr[0] - 0].sonProjectList[arr[1] - 0];
data.itemList.unshift(Value);
data.itemList[arr[0] - 0].sonProjectList.splice([arr[1] - 0], 1);
// const options = {
// id: Value.id,
// parentId: 0,
// };
const options = {
businessCode: Value.businessCode,
moveProjectId: Value.id,
targetProjectId: '',
};
emit('change', options);
}
//
clearSet(i);
emit('change', data.itemList);
return;
}
//
if (data.itemList[i].showBorder) {
if (isNumber(index)) {
const Value = data.itemList[index];
data.itemList.splice(i + 1, 0, Value);
if (i < index) {
data.itemList.splice(index + 1, 1);
} else {
data.itemList.splice(index, 1);
}
} else {
const arr = index.split('-');
const Value = data.itemList[arr[0] - 0].sonProjectList[arr[1] - 0];
data.itemList.splice(i + 1, 0, Value);
data.itemList[arr[0] - 0].sonProjectList.splice([arr[1] - 0], 1);
// const options = {
// id: Value.id,
// parentId: 0,
// };
const options = {
businessCode: Value.businessCode,
moveProjectId: Value.id,
targetProjectId: '',
};
emit('change', options);
}
//
clearSet(i);
emit('change', data.itemList);
return;
}
//
if (data.itemList[i].showSubBorder) {
if (isNumber(index)) {
const Value = data.itemList[index];
if (data.itemList[lastIndex - 1].sonProjectList && data.itemList[lastIndex - 1].sonProjectList.length) {
data.itemList[lastIndex - 1].sonProjectList.push(Value);
} else {
data.itemList[lastIndex].sonProjectList = [Value];
}
data.itemList.splice(index, 1);
//
clearSet(i);
// const options = {
// id: Value.id,
// parentId: data.itemList[lastIndex - 1].id,
// };
const options = {
businessCode: Value.businessCode,
moveProjectId: Value.id,
targetProjectId: data.itemList[lastIndex - 1].id,
};
emit('change', options);
} else {
const arr = index.split('-');
const Value = data.itemList[arr[0] - 0].sonProjectList[arr[1] - 0];
if (data.itemList[lastIndex].sonProjectList && data.itemList[lastIndex].sonProjectList.length) {
data.itemList[lastIndex].sonProjectList.push(Value);
} else {
data.itemList[lastIndex].sonProjectList = [Value];
}
data.itemList[arr[0] - 0].sonProjectList.splice([arr[1] - 0], 1);
//
clearSet(i);
// const options = {
// id: Value.id,
// parentId: data.itemList[lastIndex].id,
// };
const options = {
businessCode: Value.businessCode,
moveProjectId: Value.id,
targetProjectId: data.itemList[lastIndex].id,
};
emit('change', options);
// const options1 = {
// id: Value.id,
// parentId: 0,
// };
const options1 = {
businessCode: Value.businessCode,
moveProjectId: Value.id,
targetProjectId: '',
};
emit('change', options1);
}
return;
}
}
}
//
function clearSet(i) {
data.itemList[i].showBorder = false;
data.itemList[i].showSubBorder = false;
data.itemList[i].showTopBorder = false;
data.deltaLeft == 0;
data.showMoveImage = false;
data.setSubItem = false;
data.changeEvent = false;
data.showItemIndex = undefined;
}
//
function findOverIndex(posY) {
//
const leng = data.itemList.length * data.itemHeight; //
if (posY < data.begintop) {
return -1;
}
for (let i = 0; i < data.itemList.length; i++) {
const begin = data.itemHeight * i + data.begintop;
const end = data.itemHeight * i + data.begintop + data.itemHeight;
if (begin <= posY && end >= posY) {
return i;
}
}
if (posY > leng) {
//
return data.itemList.length - 1;
}
if (posY < data.begintop) {
return 0;
}
}
//
function delProject(id, url) {
uni.showModal({
title: '',
content: '是否删除项目?',
showCancel: true,
success: async ({ confirm }) => {
if (confirm) {
await uni.$u.api.delProject(id, url);
let flag_index = 0;
data.itemList.forEach((item, index) => {
if (item.id == id) {
flag_index = index;
}
});
data.itemList.splice(flag_index, 1);
store.commit('project/setProjects', data.itemList);
}
},
});
}
//
function importProject(id, name) {
uni.showModal({
content: '是否导入到' + name,
showCancel: true,
success: async ({ confirm }) => {
if (confirm) {
try {
const res = await uni.$u.api.import(id);
// WBS
//
emit('success');
// const { apiUrl } = Config;
// let defaultwbs = `${apiUrl}/defaultwbs`;
// res.url && (defaultwbs = res.url);
store.commit('project/setIsRefresh', 1);
setTimeout(() => {
uni.navigateTo({ url: `/pages/project/project?u=${user.value.id}&p=${res.id}&pname=${res.name}&url=${encodeURIComponent(res.url)}` });
}, 2000);
} catch (error) {
console.error('error: ', error);
emit('error', error);
}
}
},
});
}
//
function exportProject(id, url) {
uni.showModal({
title: '',
content: '是否导出项目?',
showCancel: true,
success: async ({ confirm }) => {
if (confirm) {
const data = await uni.$u.post(`${url}/tall/project/exportWbs`, { projectId: id });
// #ifdef H5
window.location.href = data.url;
// #endif
// #ifdef APP-PLUS
uni.downloadFile({
url: data.url, //
success: ({statusCode, tempFilePath}) => {
if (statusCode === 200) {
console.log('下载成功', tempFilePath);
uni.saveFile({
tempFilePath,
success:(res)=>{
uni.$ui.showToast('文件保存路径:' + res.savedFilePath);
//res.savedFilePath
//
// uni.openDocument({
// filePath: res.savedFilePath,
// success:(res)=>console.log('')
// })
},
fail:()=>console.log('下载失败')
})
}
}
});
// #endif
}
},
});
}
//
// function toWorkbench() {
// uni.navigateTo({ url: '/pages/workbench/workbench' });
// }
</script>
<style lang="scss" scoped>
.cu-item {
width: 100%;
display: flex;
align-items: center;
font-size: 14px;
}
.border-100 {
width: 92%;
height: 4rpx;
}
.border-80 {
width: 84%;
height: 2px;
margin-left: 30px;
}
.workbench-btn {
margin-right: 10px;
width: 80px;
height: 36px;
line-height: 36px;
border-radius: 18px;
overflow: hidden;
border: 1px solid #2b85e4;
background-color: #1890ff;
font-size: 12px;
color: #ffffff;
text-align: center;
}
</style>

2
components/Projects/ProjectItem.vue

@ -18,7 +18,7 @@
</view>
</view>
<view class="workbench-btn" v-if="index === 0" @click="toWorkbench">工作台</view>
<!-- <view class="workbench-btn" v-if="index === 0" @click="toWorkbench">工作台</view> -->
<view class="remind-box bg-red-500 text-white text-xs" v-if="item.remindNum">{{ item.remindNum > 99 ? '99+' : item.remindNum }}</view>

1
components/Projects/Projects.vue

@ -16,6 +16,7 @@
// arr.push(item.name);
// });
// setProjectSort(projectIdList);
emit('getProjects');
} else {
setProjectRelation(options);
}

2
manifest.json

@ -2,7 +2,7 @@
"name" : "时物链条2",
"appid" : "__UNI__6207504",
"description" : "",
"versionName" : "1.0.8",
"versionName" : "1.0.10",
"versionCode" : "100",
"transformPx" : false,
/* 5+App */

1
uni_modules/vk-uview-ui/components/u-parse/libs/MpHtmlParser.js

@ -536,6 +536,7 @@ MpHtmlParser.prototype.TagName = function(c) {
}
MpHtmlParser.prototype.AttrName = function(c) {
if (c == '=' || blankChar[c] || this.isClose()) {
console.log('6666666666666')
this.attrName = this.section();
if (blankChar[c])
while (blankChar[this.data[++this.i]]);

Loading…
Cancel
Save