Browse Source

Merge remote-tracking branch 'origin/dev' into dev

dev-V1.0.6
niujiyi 3 months ago
parent
commit
3dd6c4bd7b
  1. 2
      pom.xml
  2. 3
      zdxt-web-client/zdxt-admin-plus-ui/src/views/efcode/report/registration/indexList.vue
  3. 2
      zdxt-web-client/zdxt-efcode-enforcement-app/src/api/enforcement/plan.js
  4. 38
      zdxt-web-client/zdxt-efcode-enforcement-app/src/components/enforcement/nos/RegisterPopups.vue
  5. 31
      zdxt-web-client/zdxt-efcode-enforcement-app/src/components/enforcement/register/RegisterPopups.vue
  6. 10
      zdxt-web-client/zdxt-efcode-enforcement-app/src/views/enforcement/my/enforcementMy.vue
  7. 160
      zdxt-web-client/zdxt-efcode-enforcement-app/src/views/enforcement/my/notice/cp_notice_edit.vue
  8. 138
      zdxt-web-client/zdxt-efcode-enforcement-app/src/views/enforcement/my/plan/cp_plan_edit.vue
  9. 4
      zdxt-web-client/zdxt-efcode-enforcement-app/vite-env/.env.enforcement-dev-wmy
  10. 2
      zdxt-web-client/zdxt-efcode-enterprise-app/src/views/enterprise/enforcement/enforcementChat.vue
  11. 4
      zdxt-web-client/zdxt-efcode-enterprise-app/vite-env/.env.enterprise-dev-wmy

2
pom.xml

@ -45,7 +45,7 @@
<!-- SMS 配置 --> <!-- SMS 配置 -->
<sms4j.version>3.3.5</sms4j.version> <sms4j.version>3.3.5</sms4j.version>
<!-- 限制框架中的fastjson版本 --> <!-- 限制框架中的fastjson版本 -->
<fastjson.version>1.2.83</fastjson.version> <fastjson.version>2.0.64</fastjson.version>
<!-- 面向运行时的D-ORM依赖 --> <!-- 面向运行时的D-ORM依赖 -->
<anyline.version>8.7.3-20251210</anyline.version> <anyline.version>8.7.3-20251210</anyline.version>
<!-- 工作流配置 --> <!-- 工作流配置 -->

3
zdxt-web-client/zdxt-admin-plus-ui/src/views/efcode/report/registration/indexList.vue

@ -550,9 +550,8 @@ const closeDetailDialog = () => {
<el-descriptions-item label="未扫码原因">{{ noScanReasonOptions.find(d => d.dictValue === detailRow.checkCss)?.dictLabel || '-' }}</el-descriptions-item> <el-descriptions-item label="未扫码原因">{{ noScanReasonOptions.find(d => d.dictValue === detailRow.checkCss)?.dictLabel || '-' }}</el-descriptions-item>
<el-descriptions-item label="其他原因描述">{{ detailRow.otherReasons || '-' }}</el-descriptions-item> <el-descriptions-item label="其他原因描述">{{ detailRow.otherReasons || '-' }}</el-descriptions-item>
<el-descriptions-item label="是否投诉">{{ detailRow.isComplaint === 1 ? '是' : '否' }}</el-descriptions-item> <el-descriptions-item label="是否投诉">{{ detailRow.isComplaint === 1 ? '是' : '否' }}</el-descriptions-item>
<el-descriptions-item width="150" label="创建时间">{{ detailRow.createTime ? formatDate(detailRow) : '-' }}</el-descriptions-item> <el-descriptions-item width="150" label="创建时间">{{ (detailRow.createTime) }}</el-descriptions-item>
</el-descriptions> </el-descriptions>
</el-dialog> </el-dialog>
</div> </div>
</template> </template>

2
zdxt-web-client/zdxt-efcode-enforcement-app/src/api/enforcement/plan.js

@ -69,6 +69,6 @@ const bureauUnitBaseUrl = "/enforcementcode/bureauUnit";
// 按关键字查询执法单位内人员(分页) // 按关键字查询执法单位内人员(分页)
// params: { sysDeptId, keyword, globalSearch, pageNum, pageSize } // params: { sysDeptId, keyword, globalSearch, pageNum, pageSize }
export const searchBureauUnitUsers = (params, success, error) => export const searchBureauUnitUsers = (params, success, error) =>
_get(bureauUnitBaseUrl + "/users", params, success, error); _get(bureauUnitBaseUrl + "/queryUsersByPage", params, success, error);
// endregion // endregion

38
zdxt-web-client/zdxt-efcode-enforcement-app/src/components/enforcement/nos/RegisterPopups.vue

@ -40,18 +40,18 @@
<van-icon name="cross" class="close-icon" @click="localPersonPopup = false" /> <van-icon name="cross" class="close-icon" @click="localPersonPopup = false" />
</div> </div>
<div class="search-bar"> <div class="search-bar">
<van-search v-model="personSearchKeyword" placeholder="请输入姓名/执法证件号搜索" @search="handlePersonSearch" <van-search v-model="personSearchKeyword" placeholder="请输入至少1个字搜索" @search="handlePersonSearch"
@clear="clearPersonSearch" /> @clear="clearPersonSearch" />
<van-button class="search-btn" type="primary" @click="handlePersonSearch">搜索</van-button> <van-button class="search-btn" type="primary" @click="handlePersonSearch">搜索</van-button>
</div> </div>
<van-list v-model:loading="personLoading" :finished="personFinished" :immediate-check="false" <van-list v-model:loading="personLoading" :finished="personFinished" :immediate-check="false"
finished-text="没有更多了" @load="loadPersonList" class="person-list"> :finished-text="personFinishedText" @load="loadPersonList" class="person-list">
<div v-for="(person, index) in personList" :key="index" class="person-list-item" <div v-for="(person, index) in personList" :key="index" class="person-list-item"
@click="handleSelectPerson(person)"> @click="handleSelectPerson(person)">
<div class="person-name">{{ person.userName }}</div> <div class="person-name">{{ person.userName }}</div>
<div class="person-id">执法证件号:{{ person.lawCertificateNum || person.phonenumber || person.mobileNumber }}</div> <div class="person-id">执法证件号:{{ person.lawCertificateNum || person.phonenumber || person.mobileNumber }}</div>
</div> </div>
<van-empty v-if="personList.length === 0 && !personLoading" description="暂无数据" /> <van-empty v-if="personList.length === 0 && !personLoading" :description="personEmptyText" />
</van-list> </van-list>
</div> </div>
</van-popup> </van-popup>
@ -278,19 +278,29 @@ const personLoading = ref(false)
const personFinished = ref(false) const personFinished = ref(false)
const personPageNum = ref(1) const personPageNum = ref(1)
const personPageSize = ref(10) const personPageSize = ref(10)
const personSearched = ref(false)
const personEmptyText = computed(() => personSearched.value ? "暂无数据" : "请输入至少1个字搜索")
const personFinishedText = computed(() => personList.value.length > 0 ? "没有更多了" : "")
const loadPersonList = () => { const loadPersonList = () => {
if ((personSearchKeyword.value || "").trim().length < 1) {
personFinished.value = true
personLoading.value = false
return
}
if (personFinished.value) return if (personFinished.value) return
personLoading.value = true personLoading.value = true
getBureauUnitUsers( getBureauUnitUsers(
{ {
sysDeptId: useCommon.bureauUnitId || "", sysDeptId: useCommon.bureauUnitId || "",
keyword: personSearchKeyword.value || "", userName: personSearchKeyword.value || "",
globalSearch: "false", globalSearch: "false",
pageNum: personPageNum.value, pageNum: personPageNum.value,
pageSize: personPageSize.value, pageSize: personPageSize.value,
dataScopeId: useCommon.userId || "", dataScopeId: useCommon.userId || "",
isShowCardId: useCommon.hasLaw ? '0' : '1',
}, },
(res) => { (res) => {
console.log(res) console.log(res)
@ -334,11 +344,11 @@ const loadPersonList = () => {
} }
const initPersonList = () => { const initPersonList = () => {
personFinished.value = false personFinished.value = true
personPageNum.value = 1 personPageNum.value = 1
personList.value = [] personList.value = []
personLoading.value = false personLoading.value = false
loadPersonList() personSearched.value = false
} }
const handleSelectPerson = (person) => { const handleSelectPerson = (person) => {
@ -346,12 +356,24 @@ const handleSelectPerson = (person) => {
} }
const handlePersonSearch = () => { const handlePersonSearch = () => {
initPersonList() const keyword = (personSearchKeyword.value || "").trim()
if (keyword.length < 1) {
showToast("请输入至少1个字搜索")
return
}
personFinished.value = false
personPageNum.value = 1
personList.value = []
personSearched.value = true
loadPersonList()
} }
const clearPersonSearch = () => { const clearPersonSearch = () => {
personSearchKeyword.value = "" personSearchKeyword.value = ""
initPersonList() personFinished.value = true
personPageNum.value = 1
personList.value = []
personSearched.value = false
} }
watch(localPersonPopup, (val) => { watch(localPersonPopup, (val) => {

31
zdxt-web-client/zdxt-efcode-enforcement-app/src/components/enforcement/register/RegisterPopups.vue

@ -49,18 +49,18 @@
<van-icon name="cross" class="close-icon" @click="localPersonPopup = false" /> <van-icon name="cross" class="close-icon" @click="localPersonPopup = false" />
</div> </div>
<div class="search-bar"> <div class="search-bar">
<van-search v-model="personSearchKeyword" placeholder="请输入姓名/执法证件号搜索" @search="handlePersonSearch" <van-search v-model="personSearchKeyword" placeholder="请输入至少1个字搜索" @search="handlePersonSearch"
@clear="clearPersonSearch" /> @clear="clearPersonSearch" />
<van-button class="search-btn" type="primary" @click="handlePersonSearch">搜索</van-button> <van-button class="search-btn" type="primary" @click="handlePersonSearch">搜索</van-button>
</div> </div>
<van-list v-model:loading="personLoading" :finished="personFinished" :immediate-check="false" <van-list v-model:loading="personLoading" :finished="personFinished" :immediate-check="false"
finished-text="没有更多了" @load="loadPersonList" class="person-list"> :finished-text="personFinishedText" @load="loadPersonList" class="person-list">
<div v-for="(person, index) in personList" :key="index" class="person-list-item" <div v-for="(person, index) in personList" :key="index" class="person-list-item"
@click="handleSelectPerson(person)"> @click="handleSelectPerson(person)">
<div class="person-name">{{ person.userName }}</div> <div class="person-name">{{ person.userName }}</div>
<div class="person-id"><span class="id-label">{{person.lawCertificateNum?'执法证件号:':'联系电话:'}}</span>{{ person.lawCertificateNum || person.phonenumber || person.mobileNumber }}</div> <div class="person-id"><span class="id-label">{{person.lawCertificateNum?'执法证件号:':'联系电话:'}}</span>{{ person.lawCertificateNum || person.phonenumber || person.mobileNumber }}</div>
</div> </div>
<van-empty v-if="personList.length === 0 && !personLoading" description="暂无数据" /> <van-empty v-if="personList.length === 0 && !personLoading" :description="personEmptyText" />
</van-list> </van-list>
</div> </div>
</van-popup> </van-popup>
@ -229,23 +229,32 @@ const personPageNum = ref(1);
const personPageSize = ref(10); const personPageSize = ref(10);
const personLoading = ref(false); const personLoading = ref(false);
const personFinished = ref(false); const personFinished = ref(false);
const personSearched = ref(false);
const personEmptyText = computed(() => personSearched.value ? '暂无数据' : '请输入至少1个字搜索');
const personFinishedText = computed(() => personList.value.length > 0 ? '没有更多了' : '');
const initPersonList = () => { const initPersonList = () => {
personFinished.value = false; personFinished.value = true;
personPageNum.value = 1; personPageNum.value = 1;
personList.value = []; personList.value = [];
personLoading.value = false; personLoading.value = false;
loadPersonList(); personSearched.value = false;
}; };
const loadPersonList = () => { const loadPersonList = () => {
if ((personSearchKeyword.value || '').trim().length < 1) {
personFinished.value = true;
personLoading.value = false;
return;
}
personLoading.value = true; personLoading.value = true;
const selectedIds = props.selectedPersons.map(p => p.userId).filter(Boolean); const selectedIds = props.selectedPersons.map(p => p.userId).filter(Boolean);
const notUserId = selectedIds.length > 0 ? selectedIds.join(',') : undefined; const notUserId = selectedIds.length > 0 ? selectedIds.join(',') : undefined;
const params = { const params = {
sysDeptId: useCommon.bureauUnitId || '', sysDeptId: useCommon.bureauUnitId || '',
keyword: personSearchKeyword.value || '', userName: personSearchKeyword.value || '',
globalSearch: 'false', globalSearch: 'false',
pageNum: personPageNum.value, pageNum: personPageNum.value,
pageSize: personPageSize.value, pageSize: personPageSize.value,
@ -288,18 +297,24 @@ const loadPersonList = () => {
}; };
const handlePersonSearch = () => { const handlePersonSearch = () => {
const keyword = (personSearchKeyword.value || '').trim();
if (keyword.length < 1) {
showToast('请输入至少1个字搜索');
return;
}
personFinished.value = false; personFinished.value = false;
personPageNum.value = 1; personPageNum.value = 1;
personList.value = []; personList.value = [];
personSearched.value = true;
loadPersonList(); loadPersonList();
}; };
const clearPersonSearch = () => { const clearPersonSearch = () => {
personSearchKeyword.value = ''; personSearchKeyword.value = '';
personFinished.value = false; personFinished.value = true;
personPageNum.value = 1; personPageNum.value = 1;
personList.value = []; personList.value = [];
loadPersonList(); personSearched.value = false;
}; };
const handleSelectPerson = (person) => { const handleSelectPerson = (person) => {

10
zdxt-web-client/zdxt-efcode-enforcement-app/src/views/enforcement/my/enforcementMy.vue

@ -16,9 +16,9 @@
</div> </div>
</div> </div>
<!-- 菜单列表(仅执法人员可见) --> <!-- 菜单列表 -->
<div class="menu-wrap"> <div class="menu-wrap">
<div class="menu-card" v-if="commonStore.hasLaw"> <div class="menu-card">
<div <div
v-for="(item, idx) in menuList" v-for="(item, idx) in menuList"
:key="item.key" :key="item.key"
@ -117,6 +117,10 @@ const settingItem = {
// ========== 菜单点击 ========== // ========== 菜单点击 ==========
const onMenuClick = (item) => { const onMenuClick = (item) => {
if (!commonStore.hasLaw) {
showToast('该功能仅执法人员可用');
return;
}
switch (item.key) { switch (item.key) {
case 'notice': case 'notice':
router.push({ path: '/enforcement/notice' }); router.push({ path: '/enforcement/notice' });

160
zdxt-web-client/zdxt-efcode-enforcement-app/src/views/enforcement/my/notice/cp_notice_edit.vue

@ -170,7 +170,7 @@
<!-- 时段选择 --> <!-- 时段选择 -->
<van-popup v-model:show="showTimePicker" position="bottom" round> <van-popup v-model:show="showTimePicker" position="bottom" round>
<van-picker <van-picker
:columns="timeColumns" :columns="availableTimeColumns"
@confirm="onTimeConfirm" @confirm="onTimeConfirm"
@cancel="showTimePicker = false" @cancel="showTimePicker = false"
/> />
@ -217,17 +217,19 @@
<span class="person-picker-title">选择执法人员</span> <span class="person-picker-title">选择执法人员</span>
<van-icon name="cross" @click="showPersonPicker = false" /> <van-icon name="cross" @click="showPersonPicker = false" />
</div> </div>
<van-search <div class="search-bar">
v-model="personSearchKeyword" <van-search v-model="personSearchKeyword" placeholder="请输入至少1个字搜索"
placeholder="输入姓名/账号检索单位人员" @search="handlePersonSearch" @clear="clearPersonSearch" />
shape="round" <van-button class="search-btn" type="primary" @click="handlePersonSearch">搜索</van-button>
@update:model-value="onPersonSearchInput" </div>
/>
<div class="person-picker-body"> <div class="person-picker-body">
<div v-if="personSearching" class="person-loading"> <van-list
<van-loading size="18" />&nbsp;加载中... v-model:loading="personLoading"
</div> :finished="personFinished"
<template v-else> :finished-text="personFinishedText"
:offset="50"
@load="onPersonLoad"
>
<div <div
v-for="(user, idx) in personSearchResult" v-for="(user, idx) in personSearchResult"
:key="user.userId || idx" :key="user.userId || idx"
@ -236,12 +238,12 @@
> >
<div class="person-item-name">{{ user.fullname || user.userName }}</div> <div class="person-item-name">{{ user.fullname || user.userName }}</div>
<div class="person-item-meta"> <div class="person-item-meta">
<span>{{ user.lawCertificateNum || user.phonenumber || user.mobileNumber }}</span> <span>{{user.lawCertificateNum?'执法证件号:':'联系电话:'}} {{ user.lawCertificateNum || user.phonenumber || user.mobileNumber }}</span>
<span v-if="user.loginName" class="person-item-login">@{{ user.loginName }}</span> <!-- <span v-if="user.loginName" class="person-item-login">@{{ user.loginName }}</span> -->
</div> </div>
</div> </div>
<van-empty v-if="!personSearchResult.length" description="未检索到人员" image-size="80" /> <van-empty v-if="!personLoading && !personSearchResult.length" :description="personEmptyText" image-size="80" />
</template> </van-list>
</div> </div>
</div> </div>
</van-popup> </van-popup>
@ -354,6 +356,38 @@ const timeColumns = [
{ text: '其他(18:00-21:00)', value: 3 }, { text: '其他(18:00-21:00)', value: 3 },
]; ];
// 可选时段:执法日期为今天时过滤已过去的时段
const availableTimeColumns = computed(() => {
// 依赖弹窗显隐,打开时重新计算获取最新时间
void showTimePicker.value;
const dateStr = form.value.enforceDate;
if (!dateStr) return timeColumns;
const todayStr = `${today.getFullYear()}-${String(today.getMonth() + 1).padStart(2, '0')}-${String(today.getDate()).padStart(2, '0')}`;
if (dateStr !== todayStr) return timeColumns;
const now = new Date();
const nowMinutes = now.getHours() * 60 + now.getMinutes();
const periodEnds = { 1: 12 * 60, 2: 18 * 60, 3: 21 * 60 };
return timeColumns.filter(item => nowMinutes < periodEnds[item.value]);
});
// 默认时段设为当前可选的第一个
const syncDefaultEnforceTime = () => {
const available = availableTimeColumns.value;
if (available.length === 0) return;
const dateStr = form.value.enforceDate;
const todayStr = `${today.getFullYear()}-${String(today.getMonth() + 1).padStart(2, '0')}-${String(today.getDate()).padStart(2, '0')}`;
// 非今天(未来日期)默认取第一个(上午)
if (dateStr !== todayStr) {
form.value.enforceTime = available[0].value;
return;
}
// 今天:当前值不可用时取第一个
const currentValid = available.some(item => item.value === form.value.enforceTime);
if (!currentValid) {
form.value.enforceTime = available[0].value;
}
};
// 日期+时段展示 // 日期+时段展示
const enforceTimeDisplay = computed(() => { const enforceTimeDisplay = computed(() => {
const timeText = { 1: '上午(9:00-12:00)', 2: '下午(14:00-18:00)', 3: '其他(18:00-21:00)' }; const timeText = { 1: '上午(9:00-12:00)', 2: '下午(14:00-18:00)', 3: '其他(18:00-21:00)' };
@ -378,10 +412,16 @@ let enterpriseSearchSeq = 0;
const showPersonPicker = ref(false); const showPersonPicker = ref(false);
const personSearchKeyword = ref(''); const personSearchKeyword = ref('');
const personSearchResult = ref([]); const personSearchResult = ref([]);
const personSearching = ref(false); const personLoading = ref(false);
let personSearchTimer = null; const personFinished = ref(false);
const personPageNum = ref(1);
const personPageSize = 10;
const personSearched = ref(false);
let personSearchSeq = 0; let personSearchSeq = 0;
const personEmptyText = computed(() => personSearched.value ? '未检索到人员' : '请输入至少1个字搜索');
const personFinishedText = computed(() => personSearchResult.value.length > 0 ? '没有更多了' : '');
// 计划列表 // 计划列表
const planOptions = ref([]); const planOptions = ref([]);
const planLoading = ref(false); const planLoading = ref(false);
@ -396,6 +436,8 @@ onMounted(() => {
form.value.deptName = useCommon.deptName || ''; form.value.deptName = useCommon.deptName || '';
// 默认绑定当前用户为首位执法人员 // 默认绑定当前用户为首位执法人员
bindCurrentUserAsDefaultPerson(); bindCurrentUserAsDefaultPerson();
// 默认时段设为当前可选的第一个
syncDefaultEnforceTime();
if (isEdit.value) { if (isEdit.value) {
loadDetail(route.query.id); loadDetail(route.query.id);
@ -448,6 +490,7 @@ const loadDetail = (id, isReinitiateMode = false) => {
const onDateConfirm = ({ selectedValues }) => { const onDateConfirm = ({ selectedValues }) => {
form.value.enforceDate = selectedValues.join('-'); form.value.enforceDate = selectedValues.join('-');
showDatePicker.value = false; showDatePicker.value = false;
syncDefaultEnforceTime();
}; };
// 时段确认 // 时段确认
@ -519,24 +562,55 @@ const onAddPerson = () => {
} }
personSearchKeyword.value = ''; personSearchKeyword.value = '';
personSearchResult.value = []; personSearchResult.value = [];
personPageNum.value = 1;
personFinished.value = true;
personLoading.value = false;
personSearched.value = false;
showPersonPicker.value = true; showPersonPicker.value = true;
triggerPersonSearch('');
}; };
const onPersonSearchInput = (val) => { const handlePersonSearch = () => {
if (personSearchTimer) clearTimeout(personSearchTimer); const keyword = (personSearchKeyword.value || '').trim();
const keyword = (val || '').trim(); if (keyword.length < 1) {
personSearchTimer = setTimeout(() => triggerPersonSearch(keyword), 300); showToast('请输入至少1个字搜索');
return;
}
personPageNum.value = 1;
personFinished.value = false;
personSearchResult.value = [];
personLoading.value = true;
personSearched.value = true;
fetchPersonList(keyword);
}; };
const triggerPersonSearch = (keyword) => { const clearPersonSearch = () => {
personSearchKeyword.value = '';
personPageNum.value = 1;
personFinished.value = true;
personSearchResult.value = [];
personLoading.value = false;
personSearched.value = false;
};
// van-list 触底加载
const onPersonLoad = () => {
fetchPersonList(personSearchKeyword.value.trim());
};
// 实际发起人员检索(分页追加)
const fetchPersonList = (keyword) => {
if ((keyword || '').trim().length < 1) {
personFinished.value = true;
personLoading.value = false;
return;
}
const seq = ++personSearchSeq; const seq = ++personSearchSeq;
personSearching.value = true; personLoading.value = true;
searchBureauUnitUsers( searchBureauUnitUsers(
{ sysDeptId: useCommon.bureauUnitId || '', keyword, globalSearch: false, pageNum: 1, pageSize: 30 }, { sysDeptId: useCommon.bureauUnitId || '', userName: keyword, globalSearch: false, pageNum: personPageNum.value, pageSize: personPageSize, isShowCardId: '0' },
(res) => { (res) => {
if (seq !== personSearchSeq) return; if (seq !== personSearchSeq) return;
personSearching.value = false; personLoading.value = false;
if (res && res.code === 200 && Array.isArray(res.rows)) { if (res && res.code === 200 && Array.isArray(res.rows)) {
let rows = res.rows; let rows = res.rows;
// 过滤掉已选择的执法人员 // 过滤掉已选择的执法人员
@ -544,15 +618,26 @@ const triggerPersonSearch = (keyword) => {
const selectedIds = personList.value.map(p => String(p.id || '')).filter(Boolean); const selectedIds = personList.value.map(p => String(p.id || '')).filter(Boolean);
rows = rows.filter(item => !selectedIds.includes(String(item.userId || ''))); rows = rows.filter(item => !selectedIds.includes(String(item.userId || '')));
} }
personSearchResult.value = rows; if (personPageNum.value === 1) {
personSearchResult.value = rows;
} else {
personSearchResult.value = [...personSearchResult.value, ...rows];
}
const total = res.total || 0;
if (total <= personPageSize * personPageNum.value) {
personFinished.value = true;
} else {
personPageNum.value++;
}
} else { } else {
personSearchResult.value = []; if (personPageNum.value === 1) personSearchResult.value = [];
personFinished.value = true;
} }
}, },
() => { () => {
if (seq !== personSearchSeq) return; if (seq !== personSearchSeq) return;
personSearching.value = false; personLoading.value = false;
personSearchResult.value = []; personFinished.value = true;
} }
); );
}; };
@ -578,7 +663,6 @@ const removePerson = (index) => {
}; };
const syncPersonData = () => { const syncPersonData = () => {
console.log(personList.value);
form.value.enforceUserNames = personList.value.map(p => p.name).join(','); form.value.enforceUserNames = personList.value.map(p => p.name).join(',');
form.value.enforceUserIds = personList.value.map(p => p.id || '').join(','); form.value.enforceUserIds = personList.value.map(p => p.id || '').join(',');
form.value.enforceUserTels = personList.value.map(p => p.phone || '').join(','); form.value.enforceUserTels = personList.value.map(p => p.phone || '').join(',');
@ -870,6 +954,20 @@ const doSubmit = (isDraft) => {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
height: 100%; height: 100%;
.search-bar {
display: flex;
align-items: center;
margin: 0.3rem;
:deep(.van-search) {
padding-right: 0px;
flex: 1;
height: 34px;
}
.search-btn {
flex: none;
height: 34px;
}
}
.person-picker-header { .person-picker-header {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;

138
zdxt-web-client/zdxt-efcode-enforcement-app/src/views/enforcement/my/plan/cp_plan_edit.vue

@ -175,17 +175,19 @@
<span class="person-picker-title">选择执法人员</span> <span class="person-picker-title">选择执法人员</span>
<van-icon name="cross" @click="showPersonPicker = false" /> <van-icon name="cross" @click="showPersonPicker = false" />
</div> </div>
<van-search <div class="search-bar">
v-model="personSearchKeyword" <van-search v-model="personSearchKeyword" placeholder="请输入至少1个字搜索"
placeholder="输入姓名/账号检索单位人员" @search="handlePersonSearch" @clear="clearPersonSearch" />
shape="round" <van-button class="search-btn" type="primary" @click="handlePersonSearch">搜索</van-button>
@update:model-value="onPersonSearchInput" </div>
/>
<div class="person-picker-body"> <div class="person-picker-body">
<div v-if="personSearching" class="person-loading"> <van-list
<van-loading size="18" />&nbsp;加载中... v-model:loading="personLoading"
</div> :finished="personFinished"
<template v-else> :finished-text="personFinishedText"
:offset="50"
@load="onPersonLoad"
>
<div <div
v-for="(user, idx) in personSearchResult" v-for="(user, idx) in personSearchResult"
:key="user.userId || idx" :key="user.userId || idx"
@ -194,16 +196,16 @@
> >
<div class="person-item-name">{{ user.fullname || user.userName }}</div> <div class="person-item-name">{{ user.fullname || user.userName }}</div>
<div class="person-item-meta"> <div class="person-item-meta">
<span>{{ user.lawCertificateNum || user.phonenumber || user.mobileNumber }}</span> <span>{{user.lawCertificateNum?'执法证件号:':'联系电话:'}} {{ user.lawCertificateNum || user.phonenumber || user.mobileNumber }}</span>
<span v-if="user.loginName" class="person-item-login">@{{ user.loginName }}</span> <!-- <span v-if="user.loginName" class="person-item-login">@{{ user.loginName }}</span> -->
</div> </div>
</div> </div>
<van-empty <van-empty
v-if="!personSearchResult.length" v-if="!personLoading && !personSearchResult.length"
description="未检索到人员" :description="personEmptyText"
image-size="80" image-size="80"
/> />
</template> </van-list>
</div> </div>
</div> </div>
</van-popup> </van-popup>
@ -351,10 +353,16 @@ let enterpriseSearchSeq = 0;
const showPersonPicker = ref(false); const showPersonPicker = ref(false);
const personSearchKeyword = ref(''); const personSearchKeyword = ref('');
const personSearchResult = ref([]); const personSearchResult = ref([]);
const personSearching = ref(false); const personLoading = ref(false);
let personSearchTimer = null; const personFinished = ref(false);
const personPageNum = ref(1);
const personPageSize = 10;
const personSearched = ref(false);
let personSearchSeq = 0; let personSearchSeq = 0;
const personEmptyText = computed(() => personSearched.value ? '未检索到人员' : '请输入至少1个字搜索');
const personFinishedText = computed(() => personSearchResult.value.length > 0 ? '没有更多了' : '');
// 日期选择值 // 日期选择值
const datePickerValue = ref([ const datePickerValue = ref([
String(new Date().getFullYear()), String(new Date().getFullYear()),
@ -594,43 +602,86 @@ const onAddPerson = () => {
} }
personSearchKeyword.value = ''; personSearchKeyword.value = '';
personSearchResult.value = []; personSearchResult.value = [];
personPageNum.value = 1;
personFinished.value = true;
personLoading.value = false;
personSearched.value = false;
showPersonPicker.value = true; showPersonPicker.value = true;
// 默认先加载单位内人员列表(空关键字)
triggerPersonSearch('');
}; };
// 人员检索输入(防抖) // 人员检索(搜索按钮/回车)
const onPersonSearchInput = (val) => { const handlePersonSearch = () => {
if (personSearchTimer) clearTimeout(personSearchTimer); const keyword = (personSearchKeyword.value || '').trim();
const keyword = (val || '').trim(); if (keyword.length <1) {
personSearchTimer = setTimeout(() => triggerPersonSearch(keyword), 300); showToast('请输入至少1个字搜索');
return;
}
personPageNum.value = 1;
personFinished.value = false;
personSearchResult.value = [];
personLoading.value = true;
personSearched.value = true;
fetchPersonList(keyword);
};
// 清除搜索
const clearPersonSearch = () => {
personSearchKeyword.value = '';
personPageNum.value = 1;
personFinished.value = true;
personSearchResult.value = [];
personLoading.value = false;
personSearched.value = false;
}; };
// 实际发起人员检索 // van-list 触底加载
const triggerPersonSearch = (keyword) => { const onPersonLoad = () => {
fetchPersonList(personSearchKeyword.value.trim());
};
// 实际发起人员检索(分页追加)
const fetchPersonList = (keyword) => {
if ((keyword || '').trim().length < 1) {
personFinished.value = true;
personLoading.value = false;
return;
}
const seq = ++personSearchSeq; const seq = ++personSearchSeq;
personSearching.value = true; personLoading.value = true;
searchBureauUnitUsers( searchBureauUnitUsers(
{ {
sysDeptId: useCommon.bureauUnitId || '', sysDeptId: useCommon.bureauUnitId || '',
keyword, userName: keyword,
globalSearch: false, globalSearch: false,
pageNum: 1, pageNum: personPageNum.value,
pageSize: 30, pageSize: personPageSize,
isShowCardId: '0',
}, },
(res) => { (res) => {
if (seq !== personSearchSeq) return; if (seq !== personSearchSeq) return;
personSearching.value = false; personLoading.value = false;
if (res && res.code === 200 && Array.isArray(res.rows)) { if (res && res.code === 200 && Array.isArray(res.rows)) {
personSearchResult.value = res.rows; const data = res.rows;
if (personPageNum.value === 1) {
personSearchResult.value = data;
} else {
personSearchResult.value = [...personSearchResult.value, ...data];
}
const total = res.total || 0;
if (total <= personPageSize * personPageNum.value) {
personFinished.value = true;
} else {
personPageNum.value++;
}
} else { } else {
personSearchResult.value = []; if (personPageNum.value === 1) personSearchResult.value = [];
personFinished.value = true;
} }
}, },
() => { () => {
if (seq !== personSearchSeq) return; if (seq !== personSearchSeq) return;
personSearching.value = false; personLoading.value = false;
personSearchResult.value = []; personFinished.value = true;
} }
); );
}; };
@ -1001,6 +1052,23 @@ const doSubmit = () => {
flex-direction: column; flex-direction: column;
height: 100%; height: 100%;
.search-bar {
display: flex;
align-items: center;
margin: 0.3rem;
:deep(.van-search) {
padding-right: 0px;
flex: 1;
height: 34px;
}
.search-btn {
flex: none;
height: 34px;
}
}
.person-picker-header { .person-picker-header {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;

4
zdxt-web-client/zdxt-efcode-enforcement-app/vite-env/.env.enforcement-dev-wmy

@ -4,9 +4,9 @@ VITE_BASE_URL = '/efcode20-enf-app/api'
VITE_CONTEXT_PATH = '/efcode20-enf-app/' VITE_CONTEXT_PATH = '/efcode20-enf-app/'
# VITE_PROXY_TARGET = 'http://139.186.148.21:8080' # VITE_PROXY_TARGET = 'http://139.186.148.21:8080'
# VITE_API_URL = 'http://192.168.1.17:8080' # VITE_API_URL = 'http://192.168.1.17:8080'
VITE_PROXY_TARGET = 'http://172.16.21.213:8080' # VITE_PROXY_TARGET = 'http://172.16.21.213:8080'
# VITE_PROXY_TARGET = 'http://172.16.21.93:8080' # VITE_PROXY_TARGET = 'http://172.16.21.93:8080'
# VITE_PROXY_TARGET = 'http://172.16.20.72:8080' VITE_PROXY_TARGET = 'http://172.16.20.72:8080'
VITE_DEFAULT_LOGIN = '/enforcement/loginByPassword' VITE_DEFAULT_LOGIN = '/enforcement/loginByPassword'
VITE_APP_ENV = 'dev' VITE_APP_ENV = 'dev'
VITE_FILE_URL = '' VITE_FILE_URL = ''

2
zdxt-web-client/zdxt-efcode-enterprise-app/src/views/enterprise/enforcement/enforcementChat.vue

@ -57,7 +57,7 @@
@touchmove="onTouchMove" @touchmove="onTouchMove"
> >
<div class="msg-sender">{{ msg.msgFrom === 0 ? (msg.bureauDeptName || useCommon.bureauUnitName || '执法单位') : msg.userName }}</div> <div class="msg-sender">{{ msg.msgFrom === 0 ? (msg.bureauDeptName || useCommon.bureauUnitName || '执法单位') : msg.userName }}</div>
<span>{{ msg.content }}</span> <span v-html="msg.content"></span>
</div> </div>
</div> </div>

4
zdxt-web-client/zdxt-efcode-enterprise-app/vite-env/.env.enterprise-dev-wmy

@ -1,8 +1,8 @@
# 企业端开发环境 # 企业端开发环境
VITE_PORT = 12001 VITE_PORT = 12001
# VITE_PROXY_TARGET = 'http://139.186.148.21:8080' # VITE_PROXY_TARGET = 'http://139.186.148.21:8080'
# VITE_PROXY_TARGET = 'http://172.16.21.213:8080' VITE_PROXY_TARGET = 'http://172.16.21.213:8080'
VITE_PROXY_TARGET = 'http://172.16.21.93:8080' # VITE_PROXY_TARGET = 'http://172.16.21.93:8080'
VITE_BASE_URL = '/efcode20-ent-app/api' VITE_BASE_URL = '/efcode20-ent-app/api'
VITE_CONTEXT_PATH = '/efcode20-ent-app/' VITE_CONTEXT_PATH = '/efcode20-ent-app/'
VITE_DEFAULT_LOGIN = '/enterprise/loginByPassword' VITE_DEFAULT_LOGIN = '/enterprise/loginByPassword'

Loading…
Cancel
Save