Commit c033d8e4 authored by “yiyousong”'s avatar “yiyousong”

feat: 宜宾新需求

parent 8c24e6d7
#开发环境
NODE_ENV = "development"
VUE_APP_API_BASE_URL=http://192.168.0.98:8090
VUE_APP_API_BASE_URL=http://192.168.0.98:11078
VUE_APP_API_PHP_URL=http://192.168.0.98:8090
#VUE_APP_API_BASE_URL=http://192.168.0.98:11071/zwfw
#VUE_APP_API_BASE_URL=http://192.168.0.98:11023
......
......@@ -26,6 +26,7 @@
"moment": "^2.29.4",
"npm": "^6.13.7",
"secure-ls": "^1.2.6",
"v-scale-screen": "1.0.2",
"voca": "^1.4.0",
"vue": "^2.6.14",
"vue-barcode": "^1.3.0",
......
<template>
<v-scale-screen width="1920" height="1080" :fullScreen="true">
<div class="app">
<router-view></router-view>
<NetworkError :isShowError="isShowError"></NetworkError>
<EnabledDev :enabled="enabled"></EnabledDev>
</div>
</v-scale-screen>
</template>
<script>
......@@ -11,7 +13,7 @@ import local from "@/utils/local";
import NetworkError from "@/components/NetworkError.vue";
import EnabledDev from "@/components/EnabledDev.vue";
import mq from "@/mixin/mq";
import { getHomeInfo, getSkinList, getDeviceInfo } from "@/api";
import { getHomeInfo, getSkinList, getDeviceInfo, getAppList } from "@/api";
import { mapMutations } from "vuex";
export default {
mixins: [mq],
......@@ -33,7 +35,8 @@ export default {
this.getDeviceInfo();
if (newVal == "/" || newVal == "/home") {
this.getHomeInfo();
this.getSetinfo();
// this.getSetinfo();
this.getAppList();
}
},
},
......@@ -67,7 +70,7 @@ export default {
serverUrl: "http://192.168.0.98:11078/",
},
// devicenum: "18-93-7F-C0-AD-B5",
devicenum: "B8-13-32-87-37-82",
devicenum: "B8-2D-28-22-54-6C",
};
local.setLocal("devicenum", obj.devicenum);
local.setLocal("deviceInfo", obj.deviceInfo);
......@@ -93,6 +96,8 @@ export default {
"SET_datumList",
"SET_matterList",
"SET_deviceCode",
"SET_appList",
"SET_onlineSkin",
]),
// 简析url
urlGet() {
......@@ -118,6 +123,7 @@ export default {
this.devicenum = devicenum;
this.SET_deviceCode(devicenum);
local.setLocal("devicenum", devicenum);
if (!routeQuery["serveinfo"]) return;
// window软件测试
let serveinfo = JSON.parse(decodeURIComponent(routeQuery["serveinfo"]));
if (JSON.stringify(serveinfo) !== "{}") {
......@@ -165,6 +171,14 @@ export default {
this.SET_matterList(matterList);
}
},
// 获取应用列表
async getAppList() {
let res = await getAppList();
if (res.data.code === 1) {
let { data } = res.data;
this.SET_appList(data.slice(0, 4));
}
},
// 换肤
async getSetinfo() {
let res = await getSkinList({
......@@ -184,6 +198,7 @@ export default {
link.rel = "stylesheet";
link.href = data[0].cssFilePath;
// document.getElementsByTagName("head")[0].appendChild(link);
this.SET_onlineSkin(data[0].cssFilePath);
document.head.appendChild(link);
}
}
......
......@@ -18,6 +18,19 @@ export const getHomeInfo = (data) => {
},
});
};
// 获取应用
export const getAppList = (data) => {
let serverUrl = local.getLocal("serverUrl");
let siteId = local.getLocal("siteId");
return request({
url: `${serverUrl}basics_api/sampleform/home/app/list`,
method: "get",
params: {
siteId,
...data,
},
});
};
// 获取部门列表
export const getdeptList = (data) => {
......
<template>
<div class="loading">
<img src="@/assets/img/loading.gif" />
</div>
</template>
<script>
export default {};
</script>
<style lang="less" scoped>
.loading {
width: 100%;
height: 100%;
position: fixed;
top: 0px;
left: 0px;
display: flex;
align-items: center;
justify-content: center;
}
</style>
\ No newline at end of file
<template>
<div>
<el-drawer size="1200px" :visible.sync="drawer" direction="rtl">
<el-drawer
size="1200px"
:visible.sync="drawer"
direction="rtl"
:modal-append-to-body="false"
>
<div slot="title" class="title flex">
<span
>材料列表(共{{
......
......@@ -37,6 +37,10 @@ Vue.use(vueStatistics, { router });
// 中央事件
Vue.prototype.$bus = new Vue();
// 屏幕适配
import VScaleScreen from "v-scale-screen";
Vue.use(VScaleScreen);
Vue.config.productionTip = false;
new Vue({
......
......@@ -209,7 +209,9 @@ export default {
// 查询站点信息
this.getHomeInfo();
// 查询皮肤
this.getSetinfo();
// this.getSetinfo();
// 查询应用列表
this.getAppList();
});
// mq连接
this.clientMp(obj);
......
<template>
<!-- 应用渲染页 -->
<div class="app-show main-bg-img">
<div class="count-down">
系统将在 <span>{{ times }}</span> 秒后返回首页
</div>
<iframe
class="my-iframe"
:src="iframeUrl"
frameborder="0"
@load="changeLoading"
name="myIframe"
></iframe>
<div class="back-home flex jcc aic" @click="backHome">
<i class="iconfont icon-home mr10"></i>
<span>首页</span>
</div>
<Loading v-if="loading"></Loading>
</div>
</template>
<script>
import { mapState } from "vuex";
import Loading from "@/components/Loading.vue";
export default {
components: {
Loading,
},
data() {
return {
iframeUrl: "",
loading: true,
timeOut: null,
defaultTimes: 300,
times: 0,
};
},
created() {
this.getAppInfo();
this.isTimeOut();
},
computed: {
...mapState(["onlineSkin"]),
},
methods: {
getAppInfo() {
let {
siteId,
custUrl,
serviceApi,
appId,
newsSource,
devicenum,
// appName,
} = this.$route.query;
this.iframeUrl = `${custUrl}?siteId=${siteId}&baseUrl=${serviceApi}&appId=${appId}&newsSource=${newsSource}&devicenum=${devicenum}`;
},
changeLoading() {
this.loading = false;
if (this.onlineSkin) {
let obj = {
type: "changeSkin",
url: this.onlineSkin, // css在线地址
};
myIframe.window.postMessage(obj, "*");
}
},
backHome() {
this.$router.push("/");
},
handleBack() {
this.$router.back();
},
// 返回首页
startTimer() {
clearInterval(this.timeOut);
this.times = this.defaultTimes;
this.timeOut = setInterval(() => {
if (this.times == 0) {
this.$router.push({ path: "/" });
}
this.times -= 1;
}, 1000);
},
// 无任何操作返回首页
isTimeOut() {
if (this.$route.path == "/" || this.$route.path == "/home") {
return;
}
this.startTimer();
window.addEventListener("mousemove", this.startTimer);
window.addEventListener("mouseup", this.startTimer);
window.addEventListener("keyup", this.startTimer);
window.addEventListener("click", this.startTimer);
window.addEventListener("touchend", this.startTimer);
},
},
beforeDestroy() {
window.removeEventListener("mousemove", this.startTimer);
window.removeEventListener("mouseup", this.startTimer);
window.removeEventListener("keyup", this.startTimer);
window.removeEventListener("click", this.startTimer);
window.removeEventListener("touchend", this.startTimer);
this.timeOut && clearInterval(this.timeOut);
},
};
</script>
<style lang="less" scoped>
.app-show {
width: 100%;
height: 100%;
position: relative;
.count-down {
position: absolute;
top: 80px;
left: 160px;
color: #fff;
font-size: 24px;
// span {
// color: var(--main-theme-color);
// }
}
.my-iframe {
width: 100%;
height: 100%;
display: block;
}
.back-home {
width: 150px;
height: 64px;
border: 1px solid var(--main-h1-color);
border-radius: 8px;
position: absolute;
top: 40px;
right: 160px;
cursor: pointer;
.el-icon-arrow-left,
.icon-home {
font-size: 26px;
color: var(--main-h1-color);
}
span {
font-size: 28px;
font-family: Microsoft YaHei;
color: var(--main-h1-color);
}
}
}
</style>
......@@ -111,7 +111,8 @@
</div>
<!-- 主体 -->
<div class="main flex aic">
<div class="ranking mr25 flex flexc">
<div class="left flex flexc">
<div class="ranking flex flexc">
<div>
<img
class="ranking-title"
......@@ -149,6 +150,24 @@
<div v-else class="tac empty-text">暂无数据</div>
</div>
</div>
<div class="app-list">
<div
class="app-item"
v-for="v in appList"
:key="v.id"
@click="clickApp(v)"
>
<img
:src="
v.appIconPath.charAt(0) == '/'
? v.appIconPath
: '/' + v.appIconPath
"
/>
<span class="app-name">{{ v.appName }}</span>
</div>
</div>
</div>
<div class="right flex flexc aic jcb">
<div class="right-top flex aic jcb">
<router-link
......@@ -246,6 +265,8 @@
import MateralsList from "@/components/MateralsList.vue";
import { mapState, mapMutations } from "vuex";
import { getMaterialsList } from "@/api";
import { deviceSystem } from "@/utils";
import local from "@/utils/local";
export default {
components: {
MateralsList,
......@@ -274,7 +295,7 @@ export default {
waitTime: 2500, // 单行停顿时间(singleHeight,waitTime)
};
},
...mapState(["homeInfo", "datumList", "matterList"]),
...mapState(["homeInfo", "datumList", "matterList", "appList"]),
},
created() {
// this.getHomeInfo();
......@@ -374,6 +395,46 @@ export default {
}
return arr;
},
// 进入应用
clickApp(info) {
let system = deviceSystem();
let form = {
appId: info.id,
custUrl: info.custUrl,
serviceApi: info.serviceApi,
siteId: local.getLocal("siteId"),
devicenum: local.getLocal("devicenum"),
appName: info.appName,
};
if (info.appType == 1) {
this.$router.push({
path: "/appshow",
query: form,
});
} else {
if (system == "windows") {
window.open(info.url);
} else {
try {
androidJsSdk(
{
action: "newtab",
msg: JSON.stringify({ url: info.url, time: 300 }),
},
{
success: function (d) {},
fail: function (d) {
alert(d.msg + ",打开失败");
},
}
);
} catch (error) {
console.log(error);
alert(error);
}
}
}
},
},
};
</script>
......@@ -544,14 +605,22 @@ export default {
}
}
.main {
width: 1344px;
height: 500px;
margin-top: 40px;
.ranking {
width: 700px;
height: 495px;
justify-content: space-between;
.left {
width: 792px;
height: 100%;
background: linear-gradient(180deg, #fdefed, #fffdf8);
box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.1);
border-radius: 16px;
border: 3px solid #ffffff;
}
.ranking {
width: 100%;
flex: 1;
position: relative;
.empty-text {
font-size: 18px;
......@@ -582,6 +651,30 @@ export default {
}
}
}
.app-list {
width: 100%;
height: 124px;
padding: 20px;
display: flex;
align-items: center;
gap: 46px;
overflow: hidden;
.app-item {
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
cursor: pointer;
img {
width: 66px;
height: 66px;
}
.app-name {
font-size: 24px;
color: #333333;
}
}
}
.right {
width: 530px;
height: 495px;
......@@ -681,7 +774,7 @@ export default {
}
.footer {
width: 80%;
margin-top: 44px;
margin-top: 30px;
height: 66px;
.data-item {
height: inherit;
......
......@@ -74,6 +74,20 @@ const routes = [
},
],
},
// 应用渲染页
{
path: "/appshow",
component: Layouts,
children: [
{
path: "",
component: () => import("@/pages/appshow/AppShow.vue"),
meta: {
name: "应用页面",
},
},
],
},
];
const router = new VueRouter({
......
......@@ -14,6 +14,8 @@ export default new Vuex.Store({
deviceCode: "", // 设备编码
times: 0, // 倒计时时间
operTime: "", // 样表打开时间
appList: [], // 应用列表
onlineSkin: "", // 皮肤地址
},
getters: {
deviceCode(state) {
......@@ -27,6 +29,12 @@ export default new Vuex.Store({
},
},
mutations: {
SET_onlineSkin(state, onlineSkin) {
state.onlineSkin = onlineSkin;
},
SET_appList(state, appList) {
state.appList = appList;
},
SET_operTime(state, operTime) {
state.operTime = operTime;
},
......
// 获取当前设备系统
export function deviceSystem() {
const userAgent = navigator.userAgent;
const index = userAgent.indexOf("Android");
const device = index >= 0 ? "android" : "windows";
return device;
}
......@@ -9,4 +9,12 @@ module.exports = defineConfig({
// webpack 插件
configureWebpack: {},
transpileDependencies: true,
devServer: {
proxy: {
"/file": {
target: process.env.VUE_APP_API_BASE_URL,
changeOrigin: true,
},
},
},
});
......@@ -9548,6 +9548,11 @@ uuid@^8.3.2:
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
v-scale-screen@1.0.2:
version "1.0.2"
resolved "https://registry.npmmirror.com/v-scale-screen/-/v-scale-screen-1.0.2.tgz#8c911e3dd5ff93f56ff719511e5cafd58f0678a6"
integrity sha512-qMXPglHIs8KnhzDBdEBLcIoF3q7jgFCTWNIVPD5M0FGBkD+amYjbFUoLdKol/Xylm+pli4AHOZOqwyL6xX62SA==
v8-compile-cache@^2.0.3:
version "2.3.0"
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee"
......
......@@ -18,3 +18,38 @@ export const saveBaseSet = (data) => {
data,
});
};
// 查询应用列表
export const getAppList = (data) => {
return request({
url: "/sampleform/app/config/list",
method: "post",
data,
});
};
// 删除应用
export const delApp = (params) => {
return request({
url: "/sampleform/app/config/delete",
method: "get",
params,
});
};
// 保存应用
export const saveApp = (data) => {
return request({
url: "/sampleform/app/config/save",
method: "post",
data,
});
};
// 批量保存应用
export const batchSaveApp = (data) => {
return request({
url: "/sampleform/app/config/batchSave",
method: "post",
data,
});
};
import request from '@/utils/request'
import request from "@/utils/request";
// 获取个人站点树
export const getSiteTree = (params) => {
return request({
......@@ -6,7 +6,13 @@ export const getSiteTree = (params) => {
method: "get",
params,
});
};
};
// 获取站点应用列表
export const getSiteAppList = (data) => {
return request({
url: `base/app/list`,
method: "post",
data,
});
};
......@@ -54,6 +54,32 @@
>+ 添加词汇
</el-button>
</div>
<div class="mt20">
<div class="header">
<span class="mr15 title">首页应用</span>
<span class="tips">最多显示4个应用。</span>
</div>
<div class="mt20 flex">
<div>
<template v-for="item in showApps">
<el-tag
style="cursor: pointer"
:key="item.id"
size="medium"
closable
:disable-transitions="false"
@close="handleCloseApp(item.id)"
@click="handleEditApp(item)"
>
{{ item.appName }}
</el-tag>
</template>
</div>
<el-button class="button-new-tag" size="mini" @click="openSiteApp"
>+ 添加应用
</el-button>
</div>
</div>
<div class="mt50">
<el-button size="small" @click="handleReset"> </el-button>
<el-button size="small" type="primary" @click="handleOk"
......@@ -61,11 +87,69 @@
</el-button>
</div>
</div>
<!-- 添加应用 -->
<el-dialog
:title="isEdit ? '编辑应用' : '添加应用'"
:visible.sync="showAddApp"
width="30%"
@close="closeSiteApp"
>
<div>
<el-form
ref="form"
:model="form"
size="medium"
:rules="rules"
label-width="80px"
>
<div v-if="!isEdit">
<el-form-item label="站点应用" prop="appId">
<el-select
size="medium"
v-model="form.appId"
placeholder="请选择应用"
filterable
clearable
multiple
>
<el-option
v-for="v in selectOptions"
:key="v.id"
:label="v.appName"
:value="v.id"
></el-option>
</el-select>
</el-form-item>
</div>
<el-form-item v-else label="应用名称">
<el-input :value="form.appName" disabled> </el-input>
</el-form-item>
<el-form-item label="排序" prop="order">
<el-input-number
v-model="form.order"
controls-position="right"
:min="0"
></el-input-number>
</el-form-item>
</el-form>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="resetAddApp"> </el-button>
<el-button type="primary" @click="saveApp"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import { getBaseSetInfo, saveBaseSet } from "@/api/baseSet";
import {
getBaseSetInfo,
saveBaseSet,
getAppList,
delApp,
batchSaveApp,
} from "@/api/baseSet";
import { getSiteAppList } from "@/api/siteInfo";
import local from "@/utils/local";
import TabHeader from "@/components/TabHeader.vue";
export default {
......@@ -85,10 +169,30 @@ export default {
newsSource: "1",
printDisplay: "20",
},
siteApps: [], // 站点应用列表
showApps: [], // 终端显示应用列表
showAddApp: false,
isEdit: false, // 是否是编辑应用
form: {
appId: [], // 应用id
order: 0, // 排序
},
rules: {
appId: [{ required: true, message: "请选择应用", trigger: "change" }],
},
};
},
computed: {
selectOptions() {
return this.siteApps.filter((item) => {
return !this.showApps.some((v) => v.appId === item.id);
});
},
},
created() {
this.getBaseSetInfo();
this.getSiteAppList();
this.getAppList();
},
methods: {
// 获取基础设置
......@@ -107,6 +211,131 @@ export default {
}
}
},
// 获取站点应用
async getSiteAppList() {
let res = await getSiteAppList({
page: 1,
size: -1,
type: 1, // 终端应用
siteId: this.siteId,
});
if (res.data.code === 1) {
let { data } = res.data.data;
this.siteApps = data;
}
},
// 获取填单应用
async getAppList() {
let res = await getAppList({
page: 1,
size: -1,
});
if (res.data.code === 1) {
let { data } = res.data.data;
this.showApps = data.sort((a, b) => {
return a.order - b.order;
});
}
},
// 重置添加app表单
resetAddApp() {
this.$refs.form.resetFields();
},
// 打开站点应用弹窗
openSiteApp() {
if (this.showApps.length >= 4) {
this.$message.warning("最多添加4个应用!");
return;
}
Object.assign(this.form, this.$options.data().form);
this.form.id && this.$delete(this.form, "id");
this.isEdit = false;
this.showAddApp = true;
},
// 关闭站点应用弹窗
closeSiteApp() {
this.resetAddApp();
this.showAddApp = false;
},
// 编辑应用
handleEditApp(row) {
this.showAddApp = true;
setTimeout(() => {
this.form = { ...row, appId: [row.appId], order: row.order ?? 0 };
this.isEdit = true;
}, 10);
},
// 保存终端应用
saveApp() {
this.$refs.form.validate(async (valid) => {
if (valid) {
// let curApp = this.siteApps.find((item) => {
// return item.id === this.form.appId;
// });
if (
!this.isEdit &&
this.showApps.length + this.form.appId.length > 4
) {
this.$message.warning("最多添加4个应用!");
return;
}
let appList = this.siteApps.filter((item) => {
return this.form.appId.some((v) => v === item.id);
});
let curApp = appList.map((v) => {
let obj = {
siteId: this.siteId,
appName: v.appName,
appId: v.id,
appCode: v.appCode,
order: this.form.order,
};
if (this.form.id) {
obj.id = this.form.id;
}
return obj;
});
// let obj = {
// siteId: this.siteId,
// appName: curApp.appName,
// appId: this.form.appId,
// appCode: curApp.appCode,
// order: this.form.order,
// };
// if (this.form.id) {
// obj.id = this.form.id;
// }
let res = await batchSaveApp(curApp);
let { code } = res.data;
if (code === 1) {
this.$message.success("保存成功");
this.getAppList();
this.closeSiteApp();
}
}
});
},
// 删除终端应用
handleCloseApp(id) {
this.$confirm("确定要删除吗?", "系统提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
cancelButtonClass: "btn-custom-cancel",
type: "warning",
}).then(async () => {
let res = await delApp({ id });
let { code, msg } = res.data;
if (code === 1) {
this.$message.success(msg);
this.getAppList();
}
});
},
handleClose(tag) {
//删除当前词汇
this.baseSetInfo.hotwords = this.baseSetInfo.hotwords.filter(
......@@ -209,4 +438,7 @@ export default {
justify-content: center;
align-items: center;
}
:deep(.el-select) {
width: 100%;
}
</style>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment