|
@@ -38,7 +38,7 @@
|
|
</el-col>
|
|
</el-col>
|
|
</el-col>
|
|
</el-col>
|
|
</el-row>
|
|
</el-row>
|
|
- <el-dialog v-model="dialog.show" :title="dialog.title" :destroy-on-close="false" @close="toClose">
|
|
|
|
|
|
+ <el-dialog v-model="dialog.show" :title="dialog.title" :destroy-on-close="false" @close="toClose" :width="width">
|
|
<el-row>
|
|
<el-row>
|
|
<el-col :span="24" v-if="dialog.type == '1'">
|
|
<el-col :span="24" v-if="dialog.type == '1'">
|
|
<custom-form v-model="form" :fields="formFields" :rules="rules" @save="toSave" @draftSave="toDraftSave">
|
|
<custom-form v-model="form" :fields="formFields" :rules="rules" @save="toSave" @draftSave="toDraftSave">
|
|
@@ -76,6 +76,39 @@
|
|
</template>
|
|
</template>
|
|
</custom-form>
|
|
</custom-form>
|
|
</el-col>
|
|
</el-col>
|
|
|
|
+ <transition name="why">
|
|
|
|
+ <el-col :span="24" v-if="dialog.type == '2'" class="dialog" v-loading="isLoading" element-loading-text="智能推荐中..." :element-loading-svg="svg" element-loading-svg-view-box="-10,-10,50,50">
|
|
|
|
+ <el-empty v-if="demandtotal == 0" description="暂无数据" />
|
|
|
|
+ <div class="list" v-for="(item, index) in demandList" :key="index" @click="toView(item)">
|
|
|
|
+ <h2 class="name textMore">
|
|
|
|
+ <span>{{ item.name || '暂无' }}</span>
|
|
|
|
+ </h2>
|
|
|
|
+ <div class="other">
|
|
|
|
+ <span class="other_1">{{ getDict(item.urgent, 'urgent') || '暂无' }}</span>
|
|
|
|
+ <div class="other_2">
|
|
|
|
+ <span>应用行业:</span>
|
|
|
|
+ {{ item.field || '暂无' }}
|
|
|
|
+ </div>
|
|
|
|
+ <div class="other_2">
|
|
|
|
+ <span>资金预算:</span>
|
|
|
|
+ {{ item.money || '面议' }}
|
|
|
|
+ </div>
|
|
|
|
+ <div class="other_2">
|
|
|
|
+ <span>推荐指数:</span>
|
|
|
|
+ <el-rate size="large" v-model="item._recommend" disabled show-score text-color="#ff9900" :score-template="`${item._recommend} 星`" />
|
|
|
|
+ </div>
|
|
|
|
+ <div class="other_2 textOne">
|
|
|
|
+ <el-icon color="#0085f5"><Location /></el-icon>
|
|
|
|
+ {{ getArea(item.area) }}
|
|
|
|
+ <span class="state">{{ getDict(item.status, 'status') || '未解决' }}</span>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ <el-col :span="24" class="page">
|
|
|
|
+ <el-pagination background layout="prev, pager, next" :total="demandtotal" :page-size="demandlimit" v-model:current-page="dcurrentPage" @current-change="dchangePage" @size-change="dsizeChange" />
|
|
|
|
+ </el-col>
|
|
|
|
+ </el-col>
|
|
|
|
+ </transition>
|
|
<el-col :span="24" class="dialog_thr" v-if="dialog.type == '3'">
|
|
<el-col :span="24" class="dialog_thr" v-if="dialog.type == '3'">
|
|
<el-col :span="24" class="one">
|
|
<el-col :span="24" class="one">
|
|
<el-checkbox :indeterminate="isIndeterminate" v-model="checkAll" @change="handleCheckAllChange">全选</el-checkbox>
|
|
<el-checkbox :indeterminate="isIndeterminate" v-model="checkAll" @change="handleCheckAllChange">全选</el-checkbox>
|
|
@@ -133,6 +166,8 @@ import { TagsStore } from '@/store/api/system/tags'
|
|
import { SectorStore } from '@/store/api/platform/sector'
|
|
import { SectorStore } from '@/store/api/platform/sector'
|
|
import { RegionStore } from '@/store/api/system/region'
|
|
import { RegionStore } from '@/store/api/system/region'
|
|
import { UtilStore } from '@/store/api/util'
|
|
import { UtilStore } from '@/store/api/util'
|
|
|
|
+import { EsStore } from '@/store/api/es'
|
|
|
|
+const esStore = EsStore()
|
|
const utilStore = UtilStore()
|
|
const utilStore = UtilStore()
|
|
const regionStore = RegionStore()
|
|
const regionStore = RegionStore()
|
|
const store = AchievementStore()
|
|
const store = AchievementStore()
|
|
@@ -161,6 +196,7 @@ const cityList = ref([])
|
|
const achievementList = ref([])
|
|
const achievementList = ref([])
|
|
const tagsList = ref([])
|
|
const tagsList = ref([])
|
|
const sectorList = ref([])
|
|
const sectorList = ref([])
|
|
|
|
+const urgentList = ref([])
|
|
|
|
|
|
const form = ref({ file: [] })
|
|
const form = ref({ file: [] })
|
|
const dialog = ref({ type: '1', show: false, title: '发布成果' })
|
|
const dialog = ref({ type: '1', show: false, title: '发布成果' })
|
|
@@ -192,6 +228,26 @@ const isIndeterminate = ref(true)
|
|
// 导入文件
|
|
// 导入文件
|
|
const importActive = ref(0)
|
|
const importActive = ref(0)
|
|
const url = ref('')
|
|
const url = ref('')
|
|
|
|
+
|
|
|
|
+const isLoading = ref(false)
|
|
|
|
+const router = useRouter()
|
|
|
|
+const svg = ref(`
|
|
|
|
+ <path class="path" d="
|
|
|
|
+ M 30 15
|
|
|
|
+ L 28 17
|
|
|
|
+ M 25.61 25.61
|
|
|
|
+ A 15 15, 0, 0, 1, 15 30
|
|
|
|
+ A 15 15, 0, 1, 1, 27.99 7.5
|
|
|
|
+ L 15 15
|
|
|
|
+ " style="stroke-width: 4px; fill: rgba(0, 0, 0, 0)"/>
|
|
|
|
+ `)
|
|
|
|
+// 推荐需求列表
|
|
|
|
+const demandList = ref([])
|
|
|
|
+let demandskip = 0
|
|
|
|
+let demandlimit = 4
|
|
|
|
+const demandtotal = ref(0)
|
|
|
|
+const key = ref('')
|
|
|
|
+const width = ref('50%')
|
|
// 请求
|
|
// 请求
|
|
onMounted(async () => {
|
|
onMounted(async () => {
|
|
loading.value = true
|
|
loading.value = true
|
|
@@ -240,6 +296,9 @@ const searchOther = async () => {
|
|
// 成果状态
|
|
// 成果状态
|
|
result = await dictDataStore.query({ code: 'demandStatus', is_use: '0' })
|
|
result = await dictDataStore.query({ code: 'demandStatus', is_use: '0' })
|
|
if ($checkRes(result)) achievementList.value = result.data
|
|
if ($checkRes(result)) achievementList.value = result.data
|
|
|
|
+ // 需求紧急度
|
|
|
|
+ result = await dictDataStore.query({ code: 'urgent', is_use: '0' })
|
|
|
|
+ if ($checkRes(result)) urgentList.value = result.data
|
|
// 标签
|
|
// 标签
|
|
result = await tagsStore.query({ is_use: '0' })
|
|
result = await tagsStore.query({ is_use: '0' })
|
|
if ($checkRes(result)) tagsList.value = result.data
|
|
if ($checkRes(result)) tagsList.value = result.data
|
|
@@ -255,6 +314,7 @@ const getDict = (data, model) => {
|
|
if (data) {
|
|
if (data) {
|
|
let res
|
|
let res
|
|
if (model == 'status') res = statusList.value.find((f) => f.value == data)
|
|
if (model == 'status') res = statusList.value.find((f) => f.value == data)
|
|
|
|
+ else if (model == 'urgent') res = urgentList.value.find((f) => f.value == data)
|
|
return get(res, 'label')
|
|
return get(res, 'label')
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -291,8 +351,12 @@ const toSave = async () => {
|
|
if (get(data, 'id')) res = await store.update({ ...data, ...other })
|
|
if (get(data, 'id')) res = await store.update({ ...data, ...other })
|
|
else res = await store.create({ ...data, ...other })
|
|
else res = await store.create({ ...data, ...other })
|
|
if ($checkRes(res, true)) {
|
|
if ($checkRes(res, true)) {
|
|
- search({ skip, limit })
|
|
|
|
- toClose()
|
|
|
|
|
|
+ key.value = form.value.name
|
|
|
|
+ await search({ skip, limit })
|
|
|
|
+ await toClose()
|
|
|
|
+ await searchDemand({ demandskip, demandlimit })
|
|
|
|
+ width.value = '90%'
|
|
|
|
+ dialog.value = { type: '2', show: true, title: '相关需求推荐' }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
const toDraftSave = async () => {
|
|
const toDraftSave = async () => {
|
|
@@ -302,8 +366,12 @@ const toDraftSave = async () => {
|
|
if (get(data, 'id')) res = await store.update({ ...data, ...other })
|
|
if (get(data, 'id')) res = await store.update({ ...data, ...other })
|
|
else res = await store.create({ ...data, ...other })
|
|
else res = await store.create({ ...data, ...other })
|
|
if ($checkRes(res, true)) {
|
|
if ($checkRes(res, true)) {
|
|
- search({ skip, limit })
|
|
|
|
- toClose()
|
|
|
|
|
|
+ key.value = form.value.name
|
|
|
|
+ await search({ skip, limit })
|
|
|
|
+ await toClose()
|
|
|
|
+ await searchDemand({ demandskip, demandlimit })
|
|
|
|
+ width.value = '90%'
|
|
|
|
+ dialog.value = { type: '2', show: true, title: '相关需求推荐' }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// 审核保存
|
|
// 审核保存
|
|
@@ -313,18 +381,57 @@ const toExam = async (row) => {
|
|
const data = cloneDeep(row)
|
|
const data = cloneDeep(row)
|
|
let res = await store.update({ id: data.id, status: '0', user: user.value.id })
|
|
let res = await store.update({ id: data.id, status: '0', user: user.value.id })
|
|
if ($checkRes(res, true)) {
|
|
if ($checkRes(res, true)) {
|
|
- search({ skip, limit })
|
|
|
|
- toClose()
|
|
|
|
|
|
+ key.value = row.name
|
|
|
|
+ await search({ skip, limit })
|
|
|
|
+ await toClose()
|
|
|
|
+ await searchDemand({ demandskip, demandlimit })
|
|
|
|
+ width.value = '90%'
|
|
|
|
+ dialog.value = { type: '2', show: true, title: '相关需求推荐' }
|
|
}
|
|
}
|
|
})
|
|
})
|
|
.catch(() => {})
|
|
.catch(() => {})
|
|
}
|
|
}
|
|
|
|
+// 需求列表查询
|
|
|
|
+const searchDemand = async (query = { demandskip, demandlimit }) => {
|
|
|
|
+ demandskip = query.demandskip
|
|
|
|
+ demandlimit = query.demandlimit
|
|
|
|
+ isLoading.value = true
|
|
|
|
+ const info = { skip: demandskip, limit: demandlimit, keyword: key.value }
|
|
|
|
+ const res = await esStore.demand(info)
|
|
|
|
+ if (res.errcode == '0') {
|
|
|
|
+ demandList.value = res.data
|
|
|
|
+ demandtotal.value = res.total
|
|
|
|
+ }
|
|
|
|
+ setTimeout(() => {
|
|
|
|
+ isLoading.value = false
|
|
|
|
+ }, 3000) // 假设3秒后加载完成
|
|
|
|
+}
|
|
|
|
+const dcurrentPage = ref(1)
|
|
|
|
+// 分页
|
|
|
|
+const dchangePage = (page = dcurrentPage.value) => {
|
|
|
|
+ searchDemand({ demandskip: (page - 1) * demandlimit, demandlimit: demandlimit })
|
|
|
|
+}
|
|
|
|
+const dsizeChange = (limits) => {
|
|
|
|
+ demandlimit = limits
|
|
|
|
+ dcurrentPage.value = 1
|
|
|
|
+ searchDemand({ demandskip: 0, demandlimit: demandlimit })
|
|
|
|
+}
|
|
|
|
+// 地区
|
|
|
|
+const getArea = (data) => {
|
|
|
|
+ if (data) return data.join('-')
|
|
|
|
+ else return '暂无地区'
|
|
|
|
+}
|
|
|
|
+// 查看详情
|
|
|
|
+const toView = (item) => {
|
|
|
|
+ router.push({ path: '/demand/detail', query: { id: item.id || item._id } })
|
|
|
|
+}
|
|
const toClose = () => {
|
|
const toClose = () => {
|
|
importActive.value = 0
|
|
importActive.value = 0
|
|
url.value = ''
|
|
url.value = ''
|
|
checkedExport.value = []
|
|
checkedExport.value = []
|
|
checkAll.value = false
|
|
checkAll.value = false
|
|
- form.value = { time: [] }
|
|
|
|
|
|
+ form.value = { file: [] }
|
|
|
|
+ width.value = '50%'
|
|
dialog.value = { show: false }
|
|
dialog.value = { show: false }
|
|
}
|
|
}
|
|
// 全选
|
|
// 全选
|
|
@@ -354,7 +461,7 @@ const toTemplate = () => {
|
|
}
|
|
}
|
|
|
|
|
|
// 上传Excel
|
|
// 上传Excel
|
|
-const onSuccess = async (response, file) => {
|
|
|
|
|
|
+const onSuccess = async (response) => {
|
|
importActive.value = importActive.value + 1
|
|
importActive.value = importActive.value + 1
|
|
url.value = response.uri
|
|
url.value = response.uri
|
|
}
|
|
}
|
|
@@ -435,6 +542,95 @@ const sizeChange = (limits) => {
|
|
margin: 20px 0 0 0;
|
|
margin: 20px 0 0 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+.why-enter-from,
|
|
|
|
+.why-leave-to {
|
|
|
|
+ opacity: 0;
|
|
|
|
+ transform: scale(0.6);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.why-enter-to,
|
|
|
|
+.why-leave-from {
|
|
|
|
+ opacity: 1;
|
|
|
|
+ transform: scale(1);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.why-enter-active,
|
|
|
|
+.why-leave-active {
|
|
|
|
+ transition: all 2s ease;
|
|
|
|
+}
|
|
|
|
+.dialog {
|
|
|
|
+ display: flex;
|
|
|
|
+ justify-content: space-between;
|
|
|
|
+ flex-wrap: wrap;
|
|
|
|
+ margin-top: 20px;
|
|
|
|
+ .list {
|
|
|
|
+ position: relative;
|
|
|
|
+ margin-right: 10px;
|
|
|
|
+ margin-bottom: 10px;
|
|
|
|
+ width: 380px;
|
|
|
|
+ box-shadow: 0 0 13px 0 rgba(5, 88, 219, 0.18);
|
|
|
|
+ .name {
|
|
|
|
+ padding: 10px 20px;
|
|
|
|
+ width: 380px;
|
|
|
|
+ height: 71px;
|
|
|
|
+ background-color: #dce5ff;
|
|
|
|
+ font-size: 16px;
|
|
|
|
+ line-height: 24px;
|
|
|
|
+ color: #0d0d0d;
|
|
|
|
+ display: flex;
|
|
|
|
+ align-items: center;
|
|
|
|
+ }
|
|
|
|
+ .other {
|
|
|
|
+ padding: 10px 20px 20px;
|
|
|
|
+ .other_1 {
|
|
|
|
+ padding: 0 10px;
|
|
|
|
+ height: 25px;
|
|
|
|
+ background-color: #e6f2fd;
|
|
|
|
+ border-radius: 2px;
|
|
|
|
+ border: solid 1px #cae0f5;
|
|
|
|
+ font-size: $global-font-size-14;
|
|
|
|
+ line-height: 25px;
|
|
|
|
+ color: #0085f5;
|
|
|
|
+ }
|
|
|
|
+ .other_2 {
|
|
|
|
+ display: flex;
|
|
|
|
+ align-items: center;
|
|
|
|
+ margin-top: 15px;
|
|
|
|
+ font-size: $global-font-size-16;
|
|
|
|
+ span {
|
|
|
|
+ color: #909090;
|
|
|
|
+ }
|
|
|
|
+ .state {
|
|
|
|
+ position: absolute;
|
|
|
|
+ right: 20px;
|
|
|
|
+ bottom: 15px;
|
|
|
|
+ display: inline-block;
|
|
|
|
+ vertical-align: middle;
|
|
|
|
+ padding: 0 20px;
|
|
|
|
+ height: 30px;
|
|
|
|
+ line-height: 30px;
|
|
|
|
+ background-image: linear-gradient(90deg, #ff8a00 0, #ff5a00 100%), linear-gradient(#ff7800, #ff7800);
|
|
|
|
+ background-blend-mode: normal, normal;
|
|
|
|
+ border-radius: 14px;
|
|
|
|
+ border: solid 1px #e5e5e5;
|
|
|
|
+ color: #fff;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ .list:hover {
|
|
|
|
+ box-shadow: 0 0 5px 0 $global-color-107;
|
|
|
|
+ .name {
|
|
|
|
+ background-color: $global-color-107;
|
|
|
|
+ color: $global-color-fff;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ .page {
|
|
|
|
+ margin: 10px 0;
|
|
|
|
+ display: flex;
|
|
|
|
+ justify-content: center;
|
|
|
|
+ }
|
|
|
|
+}
|
|
.dialog_thr {
|
|
.dialog_thr {
|
|
padding: 20px;
|
|
padding: 20px;
|
|
|
|
|