Compare commits

..

No commits in common. 'main' and 'dev' have entirely different histories.
main ... dev

  1. 4
      .gitignore
  2. 2763
      package-lock.json
  3. 10
      package.json
  4. 2092
      public/static/get_cinema_info.html
  5. 1967
      public/static/get_screen_info.html
  6. 304
      public/static/report_check_ticket.html
  7. 60
      src/apis/ai_show.js
  8. 12
      src/apis/ec_api.js
  9. 15
      src/apis/group.js
  10. 2
      src/apis/mock.js
  11. 105
      src/apis/product.js
  12. 11
      src/apis/update.js
  13. 6
      src/components/ec_api/BasicConfig.vue
  14. 150
      src/components/ec_api/CardLevel.vue
  15. 25
      src/components/ec_api/CardPassword.vue
  16. 43
      src/components/ec_api/CinemaGoods.vue
  17. 192
      src/components/ec_api/MapiLockBuySelector.vue
  18. 5
      src/components/ec_api/PackageSelector.vue
  19. 185
      src/components/ec_api/TabArea.vue
  20. 1
      src/components/mock/ApiBlock.vue
  21. 203
      src/components/product/ProductAdmin.vue
  22. 30
      src/components/update/CinemaUpdate.vue
  23. 6
      src/components/update/Tips.vue
  24. 3
      src/env_config.js
  25. 18
      src/layout/components/PageAside.vue
  26. 5
      src/request/config.js
  27. 111
      src/request/index.js
  28. 11
      src/request/local.js
  29. 24
      src/request/prd.js
  30. 24
      src/router/index.js
  31. 12
      src/storage/storage.js
  32. 22
      src/store/index.js
  33. 4
      src/style.css
  34. 592
      src/views/ai_show/index.vue
  35. 240
      src/views/config/index.vue
  36. 147
      src/views/group/index.vue
  37. 17
      src/views/mock/index.vue
  38. 343
      src/views/product/index.vue
  39. 22
      src/views/update/index.vue
  40. 1823
      yarn.lock

4
.gitignore vendored

@ -22,7 +22,3 @@ dist-ssr
*.njsproj
*.sln
*.sw?
src/env_config.js*
/node_modules.zip
/.vscode/

2763
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -1,9 +1,8 @@
{
"name": "dingxin_toolbox_vue",
"private": true,
"version": "1.0.0",
"version": "0.0.0",
"type": "module",
"license": "MIT",
"scripts": {
"dev": "vite",
"build": "vite build",
@ -16,24 +15,21 @@
"ace-builds": "^1.35.4",
"axios": "^1.6.2",
"element-plus": "^2.4.3",
"js-md5": "^0.8.3",
"json-editor-vue3": "^1.0.9",
"normalize.css": "^8.0.1",
"qs": "^6.15.3",
"sortablejs": "^1.15.2",
"vite-plugin-commonjs": "^0.10.1",
"vue": "^3.3.8",
"vue-dompurify-html": "^5.3.0",
"vue-router": "^4.0.13",
"vue3-ace-editor": "^2.2.4",
"vuex": "^4.0.2",
"ws": "^8.16.0"
},
"devDependencies": {
"@vitejs/plugin-vue": "^5.2.4",
"@vitejs/plugin-vue": "^4.5.0",
"sass": "^1.69.5",
"unplugin-auto-import": "^0.17.2",
"unplugin-vue-components": "^0.26.0",
"vite": "^6.4.1"
"vite": "^5.0.0"
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1,60 +0,0 @@
import {request} from '@/request/index.js'
export const get_ai_show_data = (cinema_code, show_date, force, test_date) => {
let force_string = '0'
if (force) {
force_string = '1'
}
return request({
url: 'ai/report',
method: 'get',
params: {
cinema_code: cinema_code,
show_date: show_date,
force: force_string,
test: test_date,
}
})
}
export const get_report_date = () => {
return request({
url: 'ai/report_date',
method: 'get'
})
}
export const get_test_date_api = (cinema_code, show_date) => {
return request({
url: 'ai/test_date',
method: 'get',
params: {
cinema_code: cinema_code,
show_date: show_date,
}
})
}
export const test_prompt = (cinema_code, show_date, prompt) => {
const data = {
'cinema_code': cinema_code,
'show_date': show_date,
'prompt': prompt,
}
return request({
url: 'ai/test',
method: 'post',
data: JSON.stringify(data),
})
}
export const get_prompt_api = (cinema_code, show_date) => {
return request({
url: 'ai/get_prompt',
method: 'get',
params: {
cinema_code: cinema_code,
show_date: show_date,
}
})
}

@ -1,4 +1,4 @@
import {request, request_ip} from "@/request/index.js";
import request from "@/request/index.js";
export const get_ec_api_env = () => {
return request({
@ -77,7 +77,7 @@ export const get_ec_api_request_url = (req_data) => {
}
export const ec_api_send_request = (req_data) => {
return request_ip({
return request({
url: 'ec/send_request',
method: 'post',
data: {
@ -103,7 +103,7 @@ export const ec_api_get_suggest = (api_type, api, env, cid, pid, options) => {
if (options) {
req_params['options'] = options
}
return request_ip({
return request({
url: 'ec/get_suggest_params',
method: 'get',
params: req_params
@ -121,7 +121,7 @@ export const ec_api_get_suggest_timestamp = (api_type, api, env, cid, pid, optio
if (options !== null) {
req_params['options'] = options
}
return request_ip({
return request({
url: 'ec/get_suggest_params_timestamp',
method: 'get',
params: req_params
@ -129,7 +129,7 @@ export const ec_api_get_suggest_timestamp = (api_type, api, env, cid, pid, optio
}
export const ec_api_set_user_data = (req_data) => {
return request_ip({
return request({
url: 'ec/set_user_data',
method: 'post',
data: {
@ -145,7 +145,7 @@ export const ec_api_set_user_data = (req_data) => {
}
export const ec_api_clear_user_data = (req_data) => {
return request_ip({
return request({
url: 'ec/clear_user_data',
method: 'post',
data: {

@ -1,15 +0,0 @@
import {request} from '@/request/index.js'
export const get_group_data = () => {
return request({
url: 'group/get_group_data',
method: 'get',
})
}
export const get_group_func = () => {
return request({
url: 'group/get_group_func',
method: 'get',
})
}

@ -1,4 +1,4 @@
import {request, request_ip} from "@/request/index.js";
import request from "@/request/index.js";
export const get_overtime_show_info = (params) => {
const req_params = {

@ -1,105 +0,0 @@
import {request, request_ip} from "@/request/index.js";
// 获取项目列表
export const project_list = () => {
// console.log('project_list')
return request({
url: '/prd/project_list',
method: 'get'
})
}
// 获取产品版本列表
export const prd_list = (page_num, page_size, project = '') => {
// console.log('prd_list')
return request({
url: '/prd/prd_list',
method: 'get',
params: {
page: page_num,
page_size: page_size,
project: project
}
})
}
// 添加产品版本
export const prd_add = (params) => {
// console.log('prd_add')
const req_data = JSON.stringify({
project: params['project'],
prd_version: params['prd_version'],
prd_doc_link: params['prd_doc_link'],
prd_comment: params['prd_comment'],
is_delete: params['is_delete'],
})
return request({
url: `/prd/prd_add`,
method: 'post',
data: req_data,
})
}
// 获取产品版本列表
export const prd_get = (id) => {
// console.log('prd_get')
return request({
url: `/prd/prd_list/${id}/`,
method: 'get',
})
}
// 更新产品版本
export const prd_update = (params, id) => {
// console.log('prd_update')
const req_data = JSON.stringify({
project: params['project'],
prd_version: params['prd_version'],
prd_doc_link: params['prd_doc_link'],
prd_comment: params['prd_comment'],
is_delete: params['is_delete'],
})
return request({
url: `/prd/prd_update/${id}/`,
method: 'put',
data: req_data,
})
}
// 删除产品版本
export const prd_delete = (id) => {
// console.log('prd_delete')
return request({
url: `/prd/prd_delete/${id}/`,
method: 'delete',
})
}
// 获取历史数据
export const prd_history = (id) => {
return request({
url: `/prd/prd_history`,
method: 'get',
params: {
prd_id: id,
}
})
}
// 获取产品版本列表
export const prd_list_ax_cloud = (page_num, page_size, project = '') => {
// console.log('prd_list')
return request({
url: '/prd/prd_list/ax_cloud',
method: 'get',
params: {
page: page_num,
page_size: page_size,
project: project
}
})
}

@ -1,4 +1,4 @@
import {request, request_ip} from "@/request/index.js";
import request from "@/request/index.js";
export const cinema_list = () => {
// console.log('cinema_list')
@ -80,13 +80,6 @@ export const handle_update = (params) => {
url: '/update/update_cine/',
method: 'get',
params: params,
timeout: 6*60*1000,
})
}
export const get_client = () => {
return request({
url: '/update/client_release/',
method: 'get',
timeout: 3*60*1000,
})
}

@ -227,7 +227,7 @@ onMounted(() => {
<el-row justify="start">
<el-col :span="6">
<label class="name-label">环境:</label>
<el-select v-model="SelectEnv" placeholder="请选择" style="width: 200px" size="default"
<el-select v-model="SelectEnv" placeholder="请选择" style="width: 240px" size="default"
@change="env_on_change">
<el-option
v-for="item in EnvArray"
@ -283,7 +283,7 @@ onMounted(() => {
<el-row justify="start">
<el-col :span="6">
<label class="name-label">常用场景:</label>
<el-select v-model="SelectApiGroup" placeholder="请选择" style="width: 200px" size="default"
<el-select v-model="SelectApiGroup" placeholder="请选择" style="width: 240px" size="default"
@change="api_group_on_change">
<el-option
v-for="item in ApiGroup"
@ -301,7 +301,7 @@ onMounted(() => {
<el-col :span="6">
<label class="name-label">接口:</label>
<el-select v-model="SelectApiId" placeholder="请选择" style="width: 200px" size="default" multiple collapse-tags filterable
<el-select v-model="SelectApiId" placeholder="请选择" style="width: 240px" size="default" multiple collapse-tags filterable
collapse-tags-tooltip :clearable="true" @change="api_on_change">
<el-option
v-for="item in Api"

@ -1,150 +0,0 @@
<script setup>
import {ref, reactive, computed, watch, onMounted, onBeforeMount} from 'vue'
import {ec_api_set_user_data, ec_api_clear_user_data} from '@/apis/ec_api.js'
import {ElMessage} from "element-plus";
// 接收TabArea组件传递的参数
const props = defineProps(['level', 'data', 'base_info'])
// 定义用户选择的场次变量
const selectLevel = ref('')
const levelList = reactive([])
// 处理用户选择的数据
async function handle_set_user_data() {
let selectLevelData = {}
props.level.forEach((item) => {
if (item['levelId'] === selectLevel.value) {
selectLevelData = item
}
})
const req_data = {
api: props.data.path,
member_type: props.data.type,
format: props.data.format,
user_data: JSON.stringify(selectLevelData),
env: props.base_info.env,
cid: props.base_info.cinema,
pid: props.base_info.channel,
}
console.log('handle_set_user_data', req_data)
await ec_api_set_user_data(req_data).then(
(req) => {
if (req['result'] === 'success') {
ElMessage({message: '选择的卡级别已做为后续测试数据!', type: 'success'})
} else {
ElMessage({message: '设置用户选择卡级别数据失败!', type: 'error'})
}
}
).catch(
(err) => {
console.log(err)
ElMessage({message: '设置用户选择卡级别数据失败!', type: 'error'})
}
)
}
async function handle_clear_user_data() {
const req_data = {
api: props.data.path,
member_type: props.data.type,
env: props.base_info.env,
cid: props.base_info.cinema,
pid: props.base_info.channel,
}
console.log('handle_clear_user_data', req_data)
await ec_api_clear_user_data(req_data).then(
(req) => {
if (req['result'] === 'success') {
ElMessage({message: '选择的联名卡级别已清除,推荐参数将使用随机值!', type: 'success'})
} else {
ElMessage({message: '清除用户选择联名卡级别数据失败!', type: 'error'})
}
}
).catch(
(err) => {
console.log(err)
ElMessage({message: '清除用户选择联名卡级别数据失败!', type: 'error'})
}
)
}
onBeforeMount(() => {
console.log('CardLevel onBeforeMount')
console.log(props.level)
// 挂载时生成用于展示的数据源
props.level.forEach((item) => {
levelList.push({
key: item['levelId'],
name: item['levelName'],
fee: item['initMoney'],
type: item['typeDesc'],
ticket_discount: `${item['ticketDiscount']}%`,
online: item['enableOnlineIssue'],
data: item
})
})
console.log(levelList)
})
watch(() => selectLevel.value, () => {
console.log('selectLevel.value', selectLevel.value)
handle_set_user_data()
})
</script>
<template>
<hr id="break_line"/>
<div style="font-size: 16px; font-weight: bold; color: #909399; text-align: left; margin-bottom: 10px">选择场次:
<el-tooltip
class="box-item"
effect="dark"
content="点击清除选择后会将后台服务器中记录的选择内容清空,其他接口将通过随机获取的方式从此接口返回的数据中模拟参数"
placement="right"
>
<el-button size="small" style="font-weight: bold;color: #909399" @click="handle_clear_user_data">清除选择
</el-button>
</el-tooltip>
</div>
<el-form style="max-width: 600px; margin-left: 20px">
<el-form-item>
<el-radio-group v-model="selectLevel">
<el-radio-button v-for="s in levelList" :label="s.key" :value="s.key" :key="s.key">
<div style="text-align: left">
<div style="margin-top: 5px"><span>{{ s.key }}</span> -- <span style="font-weight: bold">{{ s.name }}</span> -- <span>{{s.type}}</span><span v-if="s.online=== '1'"> -- </span><span style="font-weight: bold">{{s.online === '1' ? '支持线上开': ''}}</span>
</div>
<div style="margin-top: 5px"><span>开卡费 {{ s.fee }} 元 </span><span>&nbsp&nbsp&nbsp&nbsp{{s.renew}}</span></div>
</div>
</el-radio-button>
</el-radio-group>
</el-form-item>
</el-form>
</template>
<style scoped>
#break_line {
margin-top: 30px;
margin-bottom: 30px;
background-color: rgba(144, 147, 153, 0.5);
height: 1px;
border: none
}
:deep(.el-radio-button) {
margin-bottom: 10px;
margin-right: 15px;
}
:deep(.el-radio-button__inner) {
width: 400px;
height: 60px;
background: #ebebeb;
color: #333;
border: 0 !important;
border-radius: 10px !important;
}
</style>

@ -1,25 +0,0 @@
<script setup>
import {ref, watch} from 'vue'
const pwd = ref('123321')
const emits = defineEmits(['get_card_pwd'])
watch(() => pwd.value, () => {
console.log(pwd.value)
emits("getCardPwd", pwd.value)
})
</script>
<template>
<el-row style="margin: 20px 0 20px 0">
<el-col :span="2"><label style="font-size: 14px; margin-left: 20px">会员卡密码:</label></el-col>
<el-col :span="7">
<el-input style="margin-left: 20px" size="small" v-model="pwd"></el-input>
</el-col>
</el-row>
</template>
<style scoped>
</style>

@ -95,24 +95,11 @@ function openOptionalPackageDialog(goods_type, goods_info) {
// 调整卖品数量
function numChange(goods_id, goods_num) {
let find_in_select = false
selectGoods.value.forEach((goods) => {
if (goods.id === goods_id) {
find_in_select = true
goods['buy_num'] = goods_num
}
})
if (find_in_select === false) {
goodsList.forEach((item) => {
if (item['id'] === goods_id) {
selectGoods.value.push(item)
console.log('可选套餐', item)
if (item['show_type'] === '可选套餐') {
openOptionalPackageDialog(item['show_type'], item)
}
}
})
}
handle_set_user_data()
}
@ -132,31 +119,18 @@ const getOptionalPackageDetail = (select) => {
handle_set_user_data()
}
// 子组件给父组件传参的回调函数
const removeOptionalPackage = (select) => {
console.log('getOptionalPackageDetail', select)
goodsDialogVisible.value = false
const g_index = selectGoods.value.indexOf(select)
console.log('g_index', g_index)
selectGoods.value.splice(g_index,1)
console.log('select', select)
console.log('removeOptionalPackage', selectGoods.value)
handle_set_user_data()
}
// 获取卖品折扣子组件的函数
const getDiscountDetail = (discount) => {
console.log('getDiscountDetail', discount)
discountDialogVisible.value = false
discount.forEach((item) => {
selectGoods.value.forEach((select) => {
if (select.id === discount.id) {
select.discount1 = item.discount1
select.discount2 = item.discount2
}
})
})
selectGoods.value.forEach((select) => {
if (select.id === discount.id) {
select.discount1 = item.discount1
select.discount2 = item.discount2
}
})
})
console.log('getDiscountDetail-selectGoods.value', selectGoods.value)
handle_set_user_data()
}
@ -236,8 +210,7 @@ watch(() => selectGoods.value, () => {
</el-checkbox-group>
</el-form-item>
</el-form>
<PackageSelector v-if="goodsDialogVisible" @get_detail="getOptionalPackageDetail"
@remove_package="removeOptionalPackage" :is_show="goodsDialogVisible"
<PackageSelector v-if="goodsDialogVisible" @get_detail="getOptionalPackageDetail" :is_show="goodsDialogVisible"
:package="optionalPackageInfo"></PackageSelector>
<GoodsDiscount v-if="discountDialogVisible" @get_discount="getDiscountDetail" :is_show="discountDialogVisible"
:goods_array="selectGoods"></GoodsDiscount>

@ -1,192 +0,0 @@
<script setup>
import {ref, watch} from 'vue'
import {ElMessageBox} from "element-plus";
// 定义props
const props = defineProps(['type'])
// 定义emits
const emits = defineEmits(["getSaleType", "getPriceType"])
// 定义选择项
const selectSaleType = props.type === 'goods' ? ref('goods') : ref('ticket')
const selectPriceType = ref("cinema_price")
const ticketPrice = ref('20.00')
const haveServiceFee = ref(true)
const ticketQuanCheck = ref(false)
const ticketQuanNum = ref('0')
const ticketQuanValue = ref('0.00')
const ticketQuanType = ref('兑换券')
const ticketQuanTypeOptions = ref([{value: '兑换券', label: '兑换券'},{value: '抵值兑换券', label: '抵值兑换券'}, {value: '代金券', label: '代金券'}])
const goodsQuanCheck = ref(false)
const goodsQuanNum = ref('0')
const goodsQuanValue = ref('0.00')
const goodsQuanType = ref('兑换券')
const goodsQuanTypeOptions = ref([{value: '兑换券', label: '兑换券'},{value: '抵值兑换券', label: '抵值兑换券'}, {value: '代金券', label: '代金券'}])
const containTicket = ["ticket", "all"]
const containGoods = ["goods", "all"]
// 检查售卖类型的变化
watch(() => selectSaleType.value, () => {
emits("getSaleType", selectSaleType.value)
})
watch(() => ticketQuanCheck.value, () => {
if (ticketQuanCheck.value) {
console.log("ticketQuanCheck.value", ticketQuanCheck.value, ticketQuanNum.value, ticketQuanValue.value)
if (ticketQuanNum.value === 0 || ticketQuanValue.value === 0) {
ElMessageBox.alert('请设置影票券数量和面值!', "影票券", {
confirmButtonText: '知道了',
callback: () => {
ticketQuanCheck.value = false
}
})
}
}
})
watch(() => goodsQuanCheck.value, () => {
if (goodsQuanCheck.value) {
console.log("goodsQuanCheck.value", goodsQuanCheck.value, goodsQuanNum.value, goodsQuanValue.value)
if (goodsQuanNum.value === 0 || goodsQuanValue.value === 0) {
ElMessageBox.alert('请设置卖品券数量和面值!', "卖品券", {
confirmButtonText: '知道了',
callback: () => {
goodsQuanCheck.value = false
}
})
}
}
})
// 检查检查定价方式的变化
watch(() => [selectPriceType.value, haveServiceFee.value, ticketPrice.value, ticketQuanCheck.value, ticketQuanNum.value, ticketQuanValue.value, goodsQuanCheck.value, goodsQuanNum.value, goodsQuanValue.value, goodsQuanType.value, ticketQuanType.value], () => {
emits("getPriceType", {
select_price_type: selectPriceType.value,
ticket_info: {
ticket_price: ticketPrice.value,
have_service_fee: haveServiceFee.value,
},
ticket_quan_check: ticketQuanCheck.value,
ticket_quan: {
ticket_quan_num: ticketQuanNum.value,
ticket_quan_value: ticketQuanValue.value,
ticket_quan_type: ticketQuanType.value,
},
goods_quan_check: goodsQuanCheck.value,
goods_quan: {
goods_quan_num: goodsQuanNum.value,
goods_quan_value: goodsQuanValue.value,
goods_quan_type: goodsQuanType.value,
}
})
})
</script>
<template>
<el-row type="flex" justify="start" align="middle" style="margin: 20px 0 10px 20px">
<el-col :span="1" style="font-size: 14px; font-weight: bold; color: #919399;" class="col-right">售卖类型</el-col>
<el-col :span="6" class="col-left">
<el-radio-group v-model="selectSaleType">
<el-radio label="ticket" v-if="props['type'] === 'ticket'">单影票</el-radio>
<el-radio label="goods" v-if="props['type'] === 'goods'">单卖品</el-radio>
<el-radio label="all" v-if="props['type'] === 'ticket'">影票加卖品</el-radio>
</el-radio-group>
</el-col>
</el-row>
<el-row type="flex" justify="start" align="middle" style="margin: 0 0 10px 20px">
<el-col :span="1" style="font-size: 14px; font-weight: bold; color: #919399;" class="col-right">定价方式</el-col>
<el-col :span="7" class="col-left">
<el-radio-group v-model="selectPriceType">
<el-radio label="cinema_price">影院定价</el-radio>
<el-radio label="third_price">三方定价</el-radio>
</el-radio-group>
</el-col>
</el-row>
<el-row v-if="selectPriceType === 'third_price'" type="flex" justify="start" align="middle" style="margin: 0 0 0 20px">
<el-col :span="1" style="font-size: 14px; font-weight: bold; color: #919399;" class="col-right">三方定价</el-col>
<el-col v-if="containTicket.includes(selectSaleType)" :span="8" class="col-left">
<span style="font-size: 14px">单张影票结算价:</span>
<el-input-number v-model="ticketPrice" :min="0.01" :max="99999.99" :step="0.01"
controls-position="right" size="small"></el-input-number>
<el-checkbox v-model="haveServiceFee" style="margin-left: 20px">是否包含服务费</el-checkbox>
</el-col>
</el-row>
<el-row v-if="selectPriceType === 'third_price' && containTicket.includes(selectSaleType)" type="flex" justify="start" align="middle" style="margin: 0 0 0 20px">
<el-col :span="1" style="font-size: 14px; font-weight: bold; color: #919399;" class="col-right"></el-col>
<el-col :span="15" class="col-left">
<span>影票券:</span>
<el-input-number v-model="ticketQuanNum" :min="0" :max="10" :step="1"
controls-position="right" size="small"></el-input-number>
<span>&nbsp张,价值&nbsp</span>
<el-input-number v-model="ticketQuanValue" :min="0.00" :max="99999.99" :step="0.01"
controls-position="right" size="small"></el-input-number>
<span>&nbsp元</span>
<span style="margin-left: 20px">券类型&nbsp</span>
<el-select
v-model="ticketQuanType"
placeholder="请选择"
size="small"
style="width: 120px"
>
<el-option
v-for="item in ticketQuanTypeOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<el-checkbox v-model="ticketQuanCheck" style="margin-left: 20px">使用影票券</el-checkbox>
</el-col>
</el-row>
<el-row v-if="selectPriceType === 'third_price' && containGoods.includes(selectSaleType)" type="flex" justify="start" align="middle" style="margin: 0 0 30px 20px">
<el-col :span="1" style="font-size: 14px; font-weight: bold; color: #919399;" class="col-right"></el-col>
<el-col :span="15" class="col-left">
<span>卖品券:</span>
<el-input-number v-model="goodsQuanNum" :min="0" :max="10" :step="1"
controls-position="right" size="small"></el-input-number>
<span>&nbsp张,价值&nbsp</span>
<el-input-number v-model="goodsQuanValue" :min="0.00" :max="99999.99" :step="0.01"
controls-position="right" size="small"></el-input-number>
<span>&nbsp元</span>
<span style="margin-left: 20px">券类型&nbsp</span>
<el-select
v-model="goodsQuanType"
placeholder="请选择"
size="small"
style="width: 120px"
>
<el-option
v-for="item in goodsQuanTypeOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<el-checkbox v-model="goodsQuanCheck" style="margin-left: 20px">使用卖品券</el-checkbox>
</el-col>
</el-row>
</template>
<style scoped>
.col-right {
display: flex;
justify-content: end;
align-items: center;
height: 100%;
}
.col-left {
display: flex;
justify-content: start;
align-items: center;
height: 100%;
margin-left: 20px;
font-size: 14px;
}
</style>

@ -53,10 +53,6 @@ function finish() {
}
}
function cancel() {
emit('remove_package', props.package)
}
// 点击关闭按键前的处理
function beforeClose(done) {
if (!checkResult()) {
@ -110,7 +106,6 @@ onBeforeMount(() => {
</el-tabs>
<template #footer>
<div class="dialog-footer">
<el-button @click="cancel">取消</el-button>
<el-button type="primary" @click="finish">完成</el-button>
</div>
</template>

@ -29,10 +29,7 @@ import CinemaGoods from "@/components/ec_api/CinemaGoods.vue";
import EcardLevel from "@/components/ec_api/EcardLevel.vue";
import CheckQuan from "@/components/ec_api/CheckQuan.vue";
import ApiLockBuySelector from "@/components/ec_api/ApiLockBuySelector.vue";
import MapiLockBuySelector from "@/components/ec_api/MapiLockBuySelector.vue";
import CardLevel from "@/components/ec_api/CardLevel.vue";
import CardPassword from "@/components/ec_api/CardPassword.vue";
import {md5} from "js-md5";
// 注册store
const store = useStore()
@ -59,31 +56,6 @@ const saleType = ref('ticket')
// 售卖接口中的支付类型
const payType = ref('cash')
// 会员售卖接口中的价格类型
const priceType = ref({
select_price_type: "cinema_price",
ticket_info: {
ticket_price: "20",
have_service_fee: true,
},
ticket_quan_check: false,
ticket_quan: {
ticket_quan_num: 0,
ticket_quan_value: "0.00",
ticket_quan_type: "兑换券",
},
goods_quan_check: false,
goods_quan: {
goods_quan_num: 0,
goods_quan_value: "0.00",
goods_quan_type: "兑换券",
},
card_num: null,
card_password: '123321',
})
const card_pwd = ref('c8837b23ff8aaa8a2dde915473ce0991')
// 表格逻辑
// 多选改变后处理逻辑
function handleParamsChange(newCheckedResult) {
@ -289,6 +261,7 @@ function send_request() {
send_btn.value = '发送'
ElMessage.error('获取请求结果失败!')
})
}
async function get_suggest(options = {sale_type: saleType.value, pay_type: payType.value}) {
@ -298,21 +271,6 @@ async function get_suggest(options = {sale_type: saleType.value, pay_type: payTy
const env = UserApiData.value.base_info['env']
const cid = UserApiData.value.base_info['cinema']
const pid = UserApiData.value.base_info['channel']
if (api_type === 'member') {
UserApiData.value.api[activeTab.value]['params'].forEach(p => {
if (p['param'] === 'card') {
const reg = /^\d*?$/
const result = reg.test(p['value'])
console.log('正则结果', result)
if (result) {
priceType.value['card_num'] = p['value']
}
}
})
options['pay_type'] = JSON.stringify(priceType.value)
console.log('options.pay_type', options.pay_type)
console.log('priceType.value', priceType.value)
}
await ec_api_get_suggest(api_type, api, env, cid, pid, options).then(
(res) => {
@ -348,21 +306,6 @@ async function get_timestamp(options = {sale_type: saleType.value, pay_type: pay
const env = UserApiData.value.base_info['env']
const cid = UserApiData.value.base_info['cinema']
const pid = UserApiData.value.base_info['channel']
if (api_type === 'member') {
UserApiData.value.api[activeTab.value]['params'].forEach(p => {
if (p['param'] === 'card') {
const reg = /^\d*?$/
const result = reg.test(p['value'])
console.log('正则结果', result)
if (result) {
priceType.value['card_num'] = p['value']
}
}
})
options['pay_type'] = JSON.stringify(priceType.value)
console.log('options.pay_type', options.pay_type)
console.log('priceType.value', priceType.value)
}
await ec_api_get_suggest_timestamp(api_type, api, env, cid, pid, options).then(
res => {
console.log('get_timestamp', res['timestamp'])
@ -391,11 +334,8 @@ function check_params(checked, unchecked) {
// 获取售卖类型并自动勾选字段
function get_sale_type(sale_type) {
saleType.value = sale_type
if (UserApiData.value.api[activeTab.value].path === "order/buy-goods")
saleType.value = 'goods'
console.log('sale_type', sale_type)
saleType.value = sale_type
if (UserApiData.value.api[activeTab.value].path === "seat/check-coupon") {
switch (saleType.value) {
case 'ticket':
@ -422,13 +362,6 @@ function get_sale_type(sale_type) {
break;
}
}
if (UserApiData.value.api[activeTab.value].path === "order/buy-goods") {
switch (saleType.value) {
case 'goods':
check_params(["goods"], ["play_id", "play_update_time", "seat", "lock_flag"]);
break;
}
}
get_timestamp()
get_suggest()
markIsChecked()
@ -490,73 +423,6 @@ function get_pay_type(pay_type) {
markIsChecked()
}
function setup_sale_type() {
console.log('UserApiData.value.api[activeTab.value].path', UserApiData.value.api[activeTab.value].path)
console.log('saleType.value', saleType.value)
if (UserApiData.value.api[activeTab.value].path === "order/buy-goods")
console.log('UserApiData.value.api[activeTab.value].path === "order/buy-goods"')
saleType.value = 'goods'
}
function get_sale_type_member(sale_type) {
saleType.value = sale_type
console.log('sale_type', sale_type)
if (UserApiData.value.api[activeTab.value].path === "seat/lock-buy") {
switch (saleType.value) {
case 'ticket':
check_params(["play_id", "play_update_time", "seat", "lock_flag"], ["goods", "goods_card_balance_pay", "goods_cash", "delivery_type", "delivery_location", "delivery_appoint_time", "contact_number"]);
break;
case 'goods':
check_params(["goods", "goods_card_balance_pay", "goods_cash"], ["play_id", "play_update_time", "seat", "lock_flag"]);
break;
case 'all':
check_params(["play_id", "play_update_time", "seat", "lock_flag", "goods", "goods_card_balance_pay", "goods_cash"], []);
break;
}
}
if (UserApiData.value.api[activeTab.value].path === "order/buy-goods") {
switch (saleType.value) {
case 'goods':
check_params(["goods", "goods_card_balance_pay", "goods_cash"], ["play_id", "play_update_time", "seat", "lock_flag"]);
break;
}
}
get_timestamp()
get_suggest()
markIsChecked()
}
function get_price_type_member(price_type) {
console.log('price_type', price_type)
priceType.value = price_type
console.log('get_price_type_member', price_type.value)
if (payType.value["select_price_type"] === "cinema_price") {
check_params(["is_cinema_price", "t3d_pay_amount"], ["is_split_service_fee", "seat_coupons"]);
} else {
check_params(["is_cinema_price", "t3d_pay_amount", "is_split_service_fee"], []);
}
if (payType.value["ticket_quan_check"] === true) {
check_params(["seat_coupons"], []);
} else {
check_params([], ["seat_coupons"]);
}
get_timestamp()
get_suggest()
markIsChecked()
}
function get_card_pwd(pwd) {
card_pwd.value = md5(pwd)
priceType.value['card_password'] = card_pwd.value
get_timestamp()
get_suggest()
markIsChecked()
}
// 用于测试,可以添加到需要的方法中
function test() {
console.log('store.state.ecApiModule.ec_api_data', store.state.ecApiModule.ec_api_data)
@ -669,24 +535,6 @@ const levelList = computed(() => {
}
}
}
if (api.path === 'cinema/card-level-rule') {
if (api.format === 'json') {
if (api.response === '{"root": "root"}') {
return []
} else {
console.log("api.handled['res']['data']['ecardLevelData']", api.handled['res']['data']['rule'])
return api.handled['res']['data']['rule']
}
}
if (api.format === 'xml' || api.format === 'html') {
if (api.response === '<root></root>') {
return []
} else {
console.log("api.handled['res']['data']['rule']", api.handled['res']['data']['rule'])
return api.handled['res']['data']['rule']
}
}
}
return []
})
@ -706,7 +554,6 @@ watch(() => store.state.ecApiModule.ec_api_data.api, (oldValue, newValue) => {
// 监测activeTab, 如果切换标签页,则执行自动勾选的函数
watch(activeTab, () => {
console.log('watch.activeTab')
setup_sale_type()
markIsChecked()
get_timestamp()
get_suggest()
@ -781,20 +628,10 @@ const ace_options = {
>
<CheckQuan v-if="api['path'] === 'seat/check-coupon'" @getQuan="get_quan_detail" @getSaleType="get_sale_type"
:cid="UserApiData['base_info']['cinema']"></CheckQuan>
<ApiLockBuySelector v-if="api['path'] === 'seat/lock-buy' && api['type'] === 'nonmember'"
@getSaleType="get_sale_type"
<ApiLockBuySelector v-if="api['path'] === 'seat/lock-buy'" @getSaleType="get_sale_type"
@getPayType="get_pay_type" type="ticket"></ApiLockBuySelector>
<ApiLockBuySelector v-if="api['path'] === 'order/buy-goods' && api['type'] === 'nonmember'"
@getSaleType="get_sale_type"
<ApiLockBuySelector v-if="api['path'] === 'order/buy-goods'" @getSaleType="get_sale_type"
@getPayType="get_pay_type" type="goods"></ApiLockBuySelector>
<MapiLockBuySelector v-if="api['path'] === 'seat/lock-buy' && api['type'] === 'member'"
@getSaleType="get_sale_type_member"
@getPriceType="get_price_type_member" type="ticket"></MapiLockBuySelector>
<MapiLockBuySelector v-if="api['path'] === 'order/buy-goods' && api['type'] === 'member'"
@getSaleType="get_sale_type_member"
@getPriceType="get_price_type_member" type="goods"></MapiLockBuySelector>
<CardPassword v-if="api['path'] === 'card/auth' || api['path'] === 'card/regist'"
@getCardPwd="get_card_pwd"></CardPassword>
<el-table
ref='ApiTableRef'
:data="UserApiData.api[api['id']].params"
@ -846,9 +683,9 @@ const ace_options = {
<el-button type="primary" @click="send_request" :loading="req_loading" :disabled="req_loading">
{{ send_btn }}
</el-button>
<!-- <el-button @click="test" >-->
<!-- 测试-->
<!-- </el-button>-->
<!-- <el-button @click="test" >-->
<!-- 测试-->
<!-- </el-button>-->
</el-col>
<el-col :span="8">
</el-col>
@ -861,12 +698,8 @@ const ace_options = {
:base_info="UserApiData.base_info"/>
<CinemaGoods v-if="goodsList.length > 0" :goods="goodsList" :data="UserApiData.api[activeTab]"
:base_info="UserApiData.base_info"/>
<EcardLevel v-if="levelList.length > 0 && api['path'] === 'ecard/ecard-levels'" :level="levelList"
:data="UserApiData.api[activeTab]"
<EcardLevel v-if="levelList.length > 0" :level="levelList" :data="UserApiData.api[activeTab]"
:base_info="UserApiData.base_info"/>
<CardLevel v-if="levelList.length > 0 && api['path'] === 'cinema/card-level-rule'" :level="levelList"
:data="UserApiData.api[activeTab]"
:base_info="UserApiData.base_info"/>
</el-tab-pane>
</el-tabs>
<el-backtop :right="300" :bottom="100" :visibility-height="100"/>

@ -24,7 +24,6 @@ const activeName = ref('download_film_info')
<iframe v-if="tab.name==='get_screen_info'" ref="iframe" src="public/static/get_screen_info.html"></iframe>
<iframe v-if="tab.name==='report_film_schedule'" ref="iframe" src="public/static/report_film_schedule.html"></iframe>
<iframe v-if="tab.name==='report_ticket'" ref="iframe" src="public/static/report_ticket.html"></iframe>
<iframe v-if="tab.name==='report_check_ticket'" ref="iframe" src="public/static/report_check_ticket.html"></iframe>
<iframe v-if="tab.name==='upload_screen_seat_info'" ref="iframe" src="public/static/upload_screen_seat_info.html"></iframe>
<iframe v-if="tab.name==='valid_error'" ref="iframe" src="public/static/valid_error.html"></iframe>
</el-tab-pane>

@ -1,203 +0,0 @@
<script setup>
import {onBeforeMount, onMounted, onBeforeUnmount, reactive, ref, unref, computed} from 'vue';
import {useStore, mapGetters, mapState} from "vuex";
import {
project_list,
prd_list,
prd_add,
prd_get,
prd_update,
prd_delete,
prd_history,
prd_list_ax_cloud
} from "@/apis/product.js";
import {storage} from "@/storage/storage.js";
import {onBeforeRouteLeave} from "vue-router";
// 注册vuex
const store = useStore()
// region 表单代码
// 点击搜索时提交的数据
const fromData = reactive({
project: '全部',
})
// region 表格数据代码
// 表格展示的数据
const tableData = ref([])
// 过滤条件数据
const projectList = ref([])
const currentPage = ref(1)
const pageSize = ref(20)
const total = ref(0)
// 处理翻页
const handleCurrentChange = (newPage) => {
currentPage.value = newPage
get_table_data(currentPage.value, pageSize.value, fromData.project)
}
const handleSizeChange = (newPageSize) => {
pageSize.value = newPageSize
get_table_data(currentPage.value, pageSize.value, fromData.project)
}
// 数据提交 点击搜索按键提交数据
const submitSearch = async () => {
tableData.value = []
await get_table_data(currentPage.value, pageSize.value, fromData.project).then(
res => {
if (Array.isArray(res)) {
tableData.value = [...res]
} else {
}
}
).catch(
err => {
}
)
}
// 通过异步请求获取影院列表数据
async function get_project_data() {
projectList.value = []
await project_list().then(res => {
if (Array.isArray(res)) {
projectList.value = [...res]
projectList.value.unshift({'id': 0, 'project_name': '全部', is_delete: false})
} else {
}
}).catch(err => {
console.log(err)
}
)
}
// 通过异步请求获取影院列表数据
async function get_table_data(page_num = currentPage.value, page_size = pageSize.value, project_val = fromData.project) {
// 获取数据
tableData.value = []
console.log('get_table_data')
console.log(project_val)
project_val = project_val === '全部' ? '' : project_val
console.log(project_val)
await prd_list_ax_cloud(page_num, page_size, project_val).then(res => {
total.value = res['count']
if (Array.isArray(res['results'])) {
tableData.value = [...res['results']]
console.log(tableData.value)
} else {
console.log('get_table_data.res is not an array')
}
}).catch(err => {
console.log(err)
}
)
}
// 定义生命周期,在加载时获取一次表格数据
onMounted(
async () => {
await get_project_data();
await get_table_data(currentPage.value, pageSize.value, fromData.project);
}
)
// endregion
</script>
<template>
<el-form
:model="fromData"
:inline="true"
class="search_form"
>
<el-form-item label="所属项目" label-width="90">
<el-select v-model="fromData.project" placeholder="请选择">
<el-option v-for="item in projectList" :key="item['project_name']" :label="item['project_name']"
:value="item['project_name']"/>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitSearch">搜索</el-button>
</el-form-item>
<!-- <el-button style="margin-right: 0">添加</el-button>-->
</el-form>
<el-table :data="tableData" style="width: 100%">
<el-table-column prop="project" label="所属项目" min-width="200"></el-table-column>
<el-table-column prop="prd_version" label="版本" min-width="200"></el-table-column>
<el-table-column prop="prd_doc_link" label="产品原型链接" min-width="300" show-overflow-tooltip>
<template v-slot="scope">
<a target="_blank" style="color:#007bff;" v-if="scope.row.prd_doc_link!=null"
@click="mark_read(scope.row.id, scope.row.update_at)"
v-bind:href="scope.row.prd_doc_link">
{{
scope.row.prd_doc_link.length > 30 ? scope.row.prd_doc_link.slice(0, 30) + '...' : scope.row.prd_doc_link
}}
</a>
</template>
</el-table-column>
<el-table-column prop="prd_comment" label="版本描述" min-width="260">
<template #default="{ row }">
<el-tooltip
class="item"
popper-class="custom-tooltip"
effect="dark"
:raw-content="true"
:content="row.prd_comment.split('\n').join('<br>')"
placement="top-end">
<span>{{ row.prd_comment.length > 10 ? row.prd_comment.slice(0, 10) + '...' : row.prd_comment }}</span>
</el-tooltip>
</template>
</el-table-column>
<el-table-column prop="update_at" label="最后更新时间" min-width="210">
</el-table-column>
<el-table-column prop="id" label="操作" min-width="120">
<template v-slot="scope">
<el-button type="primary" size="small" @click="PrdItemEdit(scope.row.id)">编辑</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination-container">
<el-pagination
v-model:current-page="currentPage"
v-model:page-size="pageSize"
:page-sizes="[10, 20, 50]"
size="small"
layout="sizes, prev, pager, next"
:total="total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
>
</el-pagination>
</div>
</template>
<style>
.pagination-container {
display: flex;
justify-content: flex-end;
margin-top: 20px;
}
.search_form {
display: flex;
justify-content: flex-start;
}
.custom-tooltip {
max-width: 500px; /* 设置最大宽度为 300px */
}
</style>

@ -1,9 +1,9 @@
<script setup>
import {onBeforeMount, ref, computed} from "vue";
import {useStore} from "vuex";
import {get_git_ver, get_update_alter, get_update_option, handle_update, get_client} from "@/apis/update.js"
import {get_git_ver, get_update_alter, get_update_option, handle_update} from "@/apis/update.js"
import Tips from "@/components/update/Tips.vue"
import config from "@/request/prd.js"
import config from "@/request/config.js"
import ProcessIcon from "@/components/update/ProcessIcon.vue";
import {ElMessageBox} from "element-plus";
@ -42,7 +42,7 @@ const createWs = () => {
console.log(ws)
if (!ws) {
console.log("建立ws连接")
ws = new WebSocket(config.direct.baseWS + "/ws/update/")
ws = new WebSocket(config.baseWS + "/ws/update/")
ws.onopen = wsOpen
ws.onmessage = wsMessage
ws.onerror = wsError
@ -158,19 +158,6 @@ onBeforeMount(async () => {
})
// endregion
// region 获取客户端版本
const client_ver = ref([])
const selectedClientVersion = ref('')
onBeforeMount(async () => {
await get_client().then(res => {
if (Array.isArray(res)) {
client_ver.value = [...res]
}
}).catch()
})
// endregion
// region 获取升级警告
const updateAlter = ref([])
onBeforeMount(
@ -200,9 +187,6 @@ onBeforeMount(
console.log(res)
res.forEach(
(value, index) => {
if (value.process === "before_sys") {
updateCmd.value.setup.push(value)
}
if (value.process === "setup") {
updateCmd.value.setup.push(value)
}
@ -368,7 +352,7 @@ const handleUpdate = async () => {
let data = {}
data = {
"ip": props.ip,
"config": {'version': selectedVersion.value, 'client': selectedClientVersion.value, 'selected': checkedCmd.value}
"config": {'version': selectedVersion.value, 'selected': checkedCmd.value}
}
store.commit("updateModule/add_update_cine", data)
@ -380,7 +364,6 @@ const handleUpdate = async () => {
let params = {
ip: props.ip,
version: selectedVersion.value,
client_ver: selectedClientVersion.value,
cmd: JSON.stringify(cmd_array)
}
@ -472,11 +455,6 @@ const handleUpdate = async () => {
:checked="cmd.is_checked" :disabled="cmd.is_force">{{ cmd.desc }}
<tips v-if="cmd.comment !==''" title="设置说明" :width="400" :content="cmd.comment"></tips>
</el-checkbox>
<el-select v-model="selectedClientVersion" filterable clearable placeholder="默认版本" :disabled="disableAll"
style="width: 180px; margin-bottom: 15px;">
<el-option
v-for="client in client_ver" :key="client.id" :label="client.client_ver" :value="client.client_ver"/>
</el-select>
</el-checkbox-group>
</el-form-item>
</el-form>

@ -37,8 +37,4 @@ const props = defineProps({
</template>
<style>
.el-popover {
height: 200px;
overflow: auto;
}
</style>
</style>

@ -1,3 +0,0 @@
export default function env_config() {
return 'local'
}

@ -38,24 +38,6 @@ const route = useRoute()
</el-icon>
<span>网售接口测试</span>
</el-menu-item>
<el-menu-item index="prd">
<el-icon>
<icon-menu/>
</el-icon>
<span>产品文档</span>
</el-menu-item>
<el-menu-item index="ai_show">
<el-icon>
<icon-menu/>
</el-icon>
<span>智能排片</span>
</el-menu-item>
<el-menu-item index="group">
<el-icon>
<icon-menu/>
</el-icon>
<span>集团数据统计</span>
</el-menu-item>
</el-menu>
</el-col>
</el-row>

@ -1,6 +1,11 @@
export default {
// method: 'get',
// baseURL: 'http://172.16.1.63:8000',
baseURL: 'http://172.16.1.168:8000',
// baseURL: 'http://127.0.0.1:8000',
// baseWS: 'ws://172.16.1.63:8000',
baseWS: 'ws://172.16.1.168:8000',
// baseWS: 'ws://127.0.0.1:8000',
headers: {
'Content-Type': 'application/json;charset=UTF-8',
'Authorization': 'token 4e63b8854974c1fdac9deb891fd74dc145b53f85'

@ -1,105 +1,40 @@
import axios from "axios";
import prd from "@/request/prd.js";
import dev from "@/request/dev.js";
import local from "@/request/local.js";
import env_config from "@/env_config.js";
import config from "@/request/config.js";
// import {ElMessage} from "element-plus";
// import {rejects} from "node:assert";
// import router from "@/router";
const environment = env_config()
const config = {
'prd': {direct: {...prd.direct}, nginx: {...prd.nginx}},
'dev': {direct: {...dev}, nginx: {...dev}},
'local': {direct: {...local}, nginx: {...local}}
}
// console.log(environment, config[environment], config[environment].direct, config[environment].nginx)
export function request(options) {
const instance = axios.create({
baseURL: config[environment].direct.baseURL,
baseWS: config[environment].direct.baseWS,
headers: {
'Content-Type': 'application/json;charset=UTF-8',
'Authorization': 'token 4e63b8854974c1fdac9deb891fd74dc145b53f85'
},
timeout: 600000,
withCredentials: true,
responseType: 'json',
})
function request(options) {
const instance = axios.create({...config})
options = {...options, instance} // 使用创建的实例
// 请求拦截器
instance.interceptors.request.use(config => {
// 处理请求前的逻辑...
return config
}, error => {
// 请求错误处理
return Promise.reject(error)
})
// 响应拦截器
instance.interceptors.response.use(response => {
// 处理响应数据
return response
}, error => {
// 处理响应错误
return Promise.reject(error)
})
return new Promise((resolve, reject) => {
instance(options)
.then(res => {
resolve(res.data)
// console.log(res.data)
})
.catch(err => {
reject(err)
})
})
}
instance.interceptors.request.use(
config => {
// 处理请求前的逻辑...
export function request_ip(options) {
const instance = axios.create({
baseURL: config[environment].direct.baseURL,
baseWS: config[environment].direct.baseWS,
headers: {
'Content-Type': 'application/json;charset=UTF-8',
'Authorization': 'token 4e63b8854974c1fdac9deb891fd74dc145b53f85'
return config
},
timeout: 60000,
withCredentials: true,
responseType: 'json',
})
options = {...options, instance} // 使用创建的实例
// 请求拦截器
instance.interceptors.request.use(config => {
// 处理请求前的逻辑...
error => {
// 请求错误处理
return config
}, error => {
// 请求错误处理
return Promise.reject(error)
})
return Promise.reject(error)
}
)
// 响应拦截器
instance.interceptors.response.use(response => {
// 处理响应数据
instance.interceptors.response.use(
response => {
// 处理响应数据
return response
}, error => {
// 处理响应错误
return response
},
error => {
// 处理响应错误
return Promise.reject(error)
})
return Promise.reject(error)
}
)
return new Promise((resolve, reject) => {
instance(options)
@ -140,4 +75,4 @@ export function request_ip(options) {
// console.log(res)
// })
// export default request
export default request

@ -1,11 +0,0 @@
export default {
baseURL: 'http://127.0.0.1:8000',
baseWS: 'ws://127.0.0.1:8000',
headers: {
'Content-Type': 'application/json;charset=UTF-8',
'Authorization': 'token 4e63b8854974c1fdac9deb891fd74dc145b53f85'
},
timeout: 60000,
withCredentials: true,
responseType: 'json',
}

@ -1,24 +0,0 @@
export default {
direct: {
baseURL: 'http://172.16.1.63:8000',
baseWS: 'ws://172.16.1.63:8000',
headers: {
'Content-Type': 'application/json;charset=UTF-8',
'Authorization': 'token 4e63b8854974c1fdac9deb891fd74dc145b53f85'
},
timeout: 60000,
withCredentials: true,
responseType: 'json',
},
nginx:{
baseURL: 'http://172.16.1.222',
baseWS: 'ws://172.16.1.63:8000',
headers: {
'Content-Type': 'application/json;charset=UTF-8',
'Authorization': 'token 4e63b8854974c1fdac9deb891fd74dc145b53f85'
},
timeout: 60000,
withCredentials: true,
responseType: 'json',
}
}

@ -41,30 +41,6 @@ const routes = [
meta:{
keepAlive: true,
}
},
{
path: 'prd',
name: 'Prd',
component: () => import('@/views/product/index.vue'),
meta:{
keepAlive: true,
}
},
{
path: 'ai_show',
name: 'AiShow',
component: () => import('@/views/ai_show/index.vue'),
meta:{
keepAlive: true,
}
},
{
path: 'group',
name: 'Group',
component: () => import('@/views/group/index.vue'),
meta:{
keepAlive: true,
}
}
]
}

@ -1,12 +0,0 @@
export const storage = {
set(key, value) {
localStorage.setItem(key, JSON.stringify(value));
},
get(key) {
const value = localStorage.getItem(key);
return value ? JSON.parse(value) : null;
},
remove(key) {
localStorage.removeItem(key);
}
}

@ -38,7 +38,7 @@ const updateModule = {
const ecApiModule = {
namespaced: true,
state: {
ec_api_data: {api: []}, // 所有api数据
ec_api_data: {api:[]}, // 所有api数据
// ec_select_api: [], // 默认选中的api
first_tab_api_id: 1,
show_tab_area: true, //是否显示表格区域
@ -76,35 +76,21 @@ const ecApiModule = {
// console.log('state.ec_api_data.api', state.ec_api_data.api)
},
handle_sort_ec_select_api: (state, payload) => {
const movedTab = state.ec_api_data.api.splice(payload.oldIndex - 1, 1)[0];
state.ec_api_data.api.splice(payload.newIndex - 1, 0, movedTab);
const movedTab = state.ec_api_data.api.splice(payload.oldIndex-1, 1)[0];
state.ec_api_data.api.splice(payload.newIndex-1, 0, movedTab);
},
add_ec_api_data: (state, payload) => {
state.ec_api_data = {api: []}
state.ec_api_data = {api:[]}
state.ec_api_data = payload
}
},
actions: {},
}
//
// const prdModule = {
// namespaced: true,
// state: {
// history_dialog_show: false,
// },
// getter: {
// dialog_change: state => {
// state.history_dialog_show = !state.history_dialog_show
// return state.history_dialog_show
// },
// },
// }
export default createStore({
modules: {
updateModule,
ecApiModule,
// prdModule,
},
})

@ -3,9 +3,9 @@
line-height: 1.5;
font-weight: 400;
color-scheme: light;
color-scheme: light dark;
color: rgba(255, 255, 255, 0.87);
background-color: rgba(255, 255, 255, 0.87);
background-color: #242424;
font-synthesis: none;
text-rendering: optimizeLegibility;

@ -1,592 +0,0 @@
<script setup>
import {onBeforeMount, ref, reactive, computed} from 'vue';
import {ElMessage} from 'element-plus'
import {get_ai_show_data, get_report_date, get_test_date_api, test_prompt, get_prompt_api} from "@/apis/ai_show.js";
// region 表格数据代码
const tableData = ref([])
const hallData = ref([])
const hallArray = ref([])
const test_date = ref()
const test_date_option = ref([])
// 表格展示的数据
const showData = ref([])
const hallType = ref({})
const createTime = ref('')
const prompt = ref('')
const tokens = ref(0)
const takeTimes = ref(0)
const realSales = ref('')
const aiSales = ref('')
const aiCount = ref('')
const compareCount = ref('')
const aiTotal = ref('')
const compareTotal = ref('')
const showResult = ref('')
const templateDate = ref('')
const result = ref(false)
const loading = ref(false)
const think = ref('')
const aiModel = ref('')
const promptVersion = ref('')
const htmlView = ref('')
// 日期控件参数
const calendarStart = ref('')
const calendarEnd = ref('')
// 对话框
const dialogFormVisible = ref(false)
const formLabelWidth = '140px'
const form = reactive({
cinema_code: '',
show_date: '',
prompt: '',
})
const testLoading = ref(false)
const promptLoading = ref(false)
// 过滤条件数据
// 计算日期
const getDefaultDate = () => {
const date = new Date()
// date.setDate(date.getDate() + 1)
const year = date.getFullYear().toString().padStart(4, "0")
const month = (date.getMonth() + 1).toString().padStart(2, "0")
const day = date.getDate().toString().padStart(2, "0")
console.log(`${year}-${month}-${day}`)
return `${year}-${month}-${day}`
}
const show_date = ref(`2026-06-12`)
// const show_date_old = ref(`2026-06-12`)
show_date.value = getDefaultDate()
// show_date_old.value = getDefaultDate()
const cinema_code = ref('11078801')
// const cinema_code_old = ref('11078801')
const force = ref(true)
const templateSwitch = ref(false)
const compareSwitch = ref('new') // template target new
// 逻辑变量
const set_default = ['mount', 'cinema', 'date']
const show_alter = () => {
ElMessage.error('没有查询到有效的智能排片数据,请调整日期和影院后再试!')
}
async function get_calendar_date() {
await get_report_date().then(res => {
if (res.status === 'success') {
calendarStart.value = res.start
calendarEnd.value = res.end
}
}).catch(err => {
console.log(err)
})
}
// 通过异步请求获取影院列表数据
async function get_data(type) {
showData.value = []
loading.value = true
prompt.value = ''
tokens.value = 0
takeTimes.value = 0
realSales.value = ''
aiSales.value = ''
showResult.value = ''
aiCount.value = ''
aiTotal.value = ''
compareTotal.value = ''
compareCount.value = ''
result.value = false
createTime.value = ''
think.value = ''
aiModel.value = ''
force.value = compareSwitch.value === 'new'
test_date_option.value = []
promptVersion.value = ''
htmlView.value = ''
console.log('get_test_date-type', type)
if (set_default.includes(type)) {
test_date.value = ''
}
await get_ai_show_data(cinema_code.value, show_date.value, force.value, test_date.value).then(res => {
if (res.status === 'success') {
console.log(res)
result.value = false
prompt.value = res.data.prompt
tokens.value = res.data.take_tokens
takeTimes.value = res.data.take_times
realSales.value = res.data.real_sales
aiSales.value = res.data.ai_sales
showResult.value = res.data.result
templateDate.value = res.data.template_date
hallType.value = res.data.hall_type
aiCount.value = res.data.ai_count
aiTotal.value = res.data.ai_total
createTime.value = res.data.create_time
think.value = res.data.think
aiModel.value = res.data.ai_model
promptVersion.value = res.data.prompt_version
if (res.data.report) {
htmlView.value = res.data.report
console.log('htmlView', htmlView.value)
}
if (compareSwitch.value === 'template') {
showData.value = res.data.template_obj
compareCount.value = res.data.template_count
compareTotal.value = res.data.template_total
} else if (compareSwitch.value === 'new') {
showData.value = res.data.real_obj
compareCount.value = res.data.real_count
compareTotal.value = res.data.real_total
} else {
showData.value = res.data.target_obj
compareCount.value = res.data.target_count
compareTotal.value = res.data.target_total
}
console.log(showData.value, prompt.value, tokens.value, takeTimes.value, realSales.value, aiSales.value, showResult.value)
formatTableData()
loading.value = false
// cinema_code_old.value = cinema_code.value
// show_date_old.value = show_date.value
get_test_date(type)
} else {
tableData.value = []
result.value = true
show_alter()
loading.value = false
get_test_date(type)
}
}).catch(err => {
console.log(err)
}
)
loading.value = false
}
// 处理表格数据
function formatTableData() {
hallArray.value = []
hallData.value = []
tableData.value = []
let temp = 0;
showData.value.forEach((item, index) => {
tableData.value.push({
hall: item[0] + '\n\n支持制式:' + hallType.value[item[0]],
ai_show: item[2],
ai_language: item[4],
ai_start: item[5],
ai_end: item[6],
ai_length: item[7],
ai_duration: item[8],
real_show: item[9],
real_language: item[11],
real_start: item[12],
real_end: item[13],
real_length: item[14],
real_duration: item[15],
})
if (hallArray.value.indexOf(item[0]) >= 0) {
hallData.value[temp] += 1
hallData.value.push(0)
} else {
hallArray.value.push(item[0])
temp = index
hallData.value.push(1)
}
})
console.log('hallArray.value', hallArray.value)
console.log('hallData.value', hallData.value)
}
// 通过接口获取测试数据的下拉列表数据 type mount,date,cinema,test, compare
const get_test_date = (type) => {
get_test_date_api(cinema_code.value, show_date.value).then(res => {
if (res.status === 'success') {
test_date_option.value = []
res.date.forEach((item, index) => {
const test_label = item[1] === true?item[0]+'-手工测试':item[0]
test_date_option.value.push({'value': item[0], label: test_label})
})
console.log('get_test_date-type', type)
if (set_default.includes(type)) {
test_date.value = test_date_option.value[0]['value']
}
}
})
}
// 提交测试提示词
async function requestTest() {
testLoading.value = true
dialogFormVisible.value = false
await test_prompt(form.cinema_code, form.show_date, form.prompt).then(res => {
if (res.status === 'success') {
get_test_date()
console.log(res)
}
}).catch(err => {
console.log(err)
})
testLoading.value = false
form.cinema_code = ''
form.show_date = ''
form.prompt = ''
}
async function generalPrompt() {
promptLoading.value = true
form.prompt = ''
await get_prompt_api(form.cinema_code, form.show_date).then(res => {
if (res.status === 'success') {
form.prompt = res.data
}
promptLoading.value = false
}).catch(err => {
console.log(err)
})
promptLoading.value = false
}
const testButton = computed(() => {
if (testLoading.value === true) {
return 'AI排片中'
} else {
return '测试提示词'
}
})
// 处理表格合并
const objectSpanMethod = ({row, column, rowIndex, columnIndex}) => {
if (column.property === 'hall') {
const rowSpan = hallData.value[rowIndex]
if (hallData.value[rowIndex] === 0) {
return {
rowspan: rowSpan,
colspan: 0,
}
} else {
return {
rowspan: rowSpan,
colspan: 1,
}
}
} else {
return {
rowspan: 1,
colspan: 1,
}
}
}
// 日历禁用日期
const disabledDate = (time) => {
const start = new Date(calendarStart.value)
const end = new Date(calendarEnd.value)
return time.getTime() < start || time.getTime() > end
}
// 日历禁用日期
const disabledFormDate = (time) => {
const today = new Date()
const start = new Date()
const end = new Date().setDate(today.getDate() + 7)
return time.getTime() < start || time.getTime() > end
}
const tableHeader = computed(() => {
if (compareSwitch.value === 'new') {
return '目标日期最新排片数据(实时更新)'
} else if (compareSwitch.value === 'template') {
return '模板日期排片数据'
} else {
return '目标日期历史排片数据'
}
})
const compareDesc = computed(() => {
if (compareSwitch.value === 'new') {
return '排片占比(AI/目标日期最新排片数据)'
} else if (compareSwitch.value === 'template') {
return '排片占比(AI/模板日期排片数据)'
} else {
return '排片占比(AI/目标日期历史排片数据)'
}
})
// 定义生命周期,在加载时获取一次表格数据
onBeforeMount(
async () => {
await get_calendar_date()
await get_data('mount')
}
)
// endregion
</script>
<template>
<el-row align="middle">
<el-col :span="2">
<el-text>排片目标日期</el-text>
</el-col>
<el-col :span="3">
<el-date-picker
v-model="show_date"
type="date"
placeholder="选择排片日期"
size="default"
:disabled-date="disabledDate"
value-format="YYYY-MM-DD"
@change="get_data('date')"
style="width: 140px"
/>
</el-col>
<el-col :span="12">
<el-radio-group v-model="cinema_code" @change="get_data('cinema')">
<el-radio-button value="11078801" label="11078801">保利国际影城北京凯德大峡谷店</el-radio-button>
<el-radio-button value="31073101" label="31073101">SFC上影(永华店)</el-radio-button>
<el-radio-button value="33040301" label="33040301">宁波影都(东门口店)</el-radio-button>
</el-radio-group>
</el-col>
<el-col :span="3">
<el-text>智能排片生成时间:</el-text>
</el-col>
<el-col :span="3">
<el-text>{{ createTime }}</el-text>
</el-col>
</el-row>
<el-row style="margin: 10px 0 0 0" align="middle">
<el-col :span="2">
<el-tooltip
class="box-item"
effect="dark"
content="最新排片数据:实时获取影院目标日期的排片数据;模板日期排片数据:AI生成排片时刻,参考的模板日期排片数据(历史数据不更新);目标日期排片数据:AI生成排片时刻,目标日期的排片数据(历史数据不更新)"
placement="top"
>
<el-text>对比数据选择</el-text>
</el-tooltip>
</el-col>
<el-col :span="9">
<el-radio-group v-model="compareSwitch" @change="get_data('compare')">
<el-radio value="new" label="new">最新排片数据</el-radio>
<el-radio value="template" label="template">模板日期排片数据</el-radio>
<el-radio value="target" label="target">目标日期排片数据</el-radio>
</el-radio-group>
</el-col>
<el-col :span="2" align="right">
<el-text>选择数据:</el-text>
</el-col>
<el-col :span="4">
<el-select v-model="test_date" placeholder="请选择" :clearable="true"
@change="get_data('test')" style="width: 240px">
<el-option
v-for="item in test_date_option"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-col>
<el-col :span="4" v-if="compareSwitch==='template'">
<el-text>模板日期:{{ templateDate }}</el-text>
</el-col>
</el-row>
<el-row style="margin: 10px 0 20px 0" align="middle">
<el-col :span="2">
<el-button type="primary" @click="dialogFormVisible = true" :disabled="testLoading" :loading="testLoading">
{{ testButton }}
</el-button>
</el-col>
</el-row>
<el-dialog v-model="dialogFormVisible" title="测试提示词" width="800" style="max-height: 800px">
<el-form :model="form">
<el-form-item label="目标日期" :label-width="formLabelWidth">
<el-date-picker
v-model="form.show_date"
type="date"
placeholder="选择排片日期"
size="default"
:disabled-date="disabledFormDate"
value-format="YYYY-MM-DD"
style="width: 140px"
/>
</el-form-item>
<el-form-item label="测试影院" :label-width="formLabelWidth">
<el-select v-model="form.cinema_code" placeholder="请选择" style="width: 260px">
<el-option label="保利国际影城北京凯德大峡谷店" value="11078801"/>
<el-option label="SFC上影(永华店)" value="31073101"/>
<el-option label="宁波影都(东门口店)" value="33040301"/>
</el-select>
</el-form-item>
<el-form-item label="" :label-width="formLabelWidth">
<el-button type="primary" @click="generalPrompt" :loading="promptLoading">
生成提示词
</el-button>
</el-form-item>
<el-form-item label="提示词" :label-width="formLabelWidth">
<el-input
v-model="form.prompt"
style="width: 600px"
placeholder="请输入提示词"
type="textarea"
:autosize="{ minRows: 6, maxRows: 15 }"
clearable
/>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="dialogFormVisible = false">取消</el-button>
<el-button type="primary" @click="requestTest">
提交
</el-button>
</div>
</template>
</el-dialog>
<el-table :data="tableData" style="width: 100%" v-loading="loading" :span-method="objectSpanMethod">
<el-table-column prop="hall" label="影厅别名" min-width="160"></el-table-column>
<el-table-column label="智能排片" align="center">
<el-table-column prop="ai_show" label="影片别名" min-width="160"></el-table-column>
<el-table-column prop="ai_language" label="语言" min-width="60"></el-table-column>
<el-table-column prop="ai_start" label="开始时间" min-width="80"></el-table-column>
<el-table-column prop="ai_end" label="结束时间" min-width="80"></el-table-column>
<el-table-column prop="ai_length" label="片长" min-width="60"></el-table-column>
<el-table-column prop="ai_duration" label="场间" min-width="60"></el-table-column>
</el-table-column>
<el-table-column :label="tableHeader" align="center">
<el-table-column prop="real_show" label="影片别名" min-width="160"></el-table-column>
<el-table-column prop="real_language" label="语言" min-width="60"></el-table-column>
<el-table-column prop="real_start" label="开始时间" min-width="80"></el-table-column>
<el-table-column prop="real_end" label="结束时间" min-width="80"></el-table-column>
<el-table-column prop="real_length" label="片长" min-width="60"></el-table-column>
<el-table-column prop="real_duration" label="场间" min-width="60"></el-table-column>
</el-table-column>
</el-table>
<el-row style="margin-top: 30px">
<el-text style="font-weight: bold" size="large">相关数据:</el-text>
</el-row>
<el-row>
<el-col :span="3" align="right">
<el-text style="font-weight: bold">调用模型:</el-text>
</el-col>
<el-col :span="4" align="left">
<el-text>{{ aiModel }}</el-text>
</el-col>
</el-row>
<el-row>
<el-col :span="3" align="right">
<el-text style="font-weight: bold">智能排片预估销售额:</el-text>
</el-col>
<el-col :span="4" align="left">
<el-text>{{ aiSales }}元</el-text>
</el-col>
</el-row>
<el-row>
<el-col :span="3" align="right">
<el-text style="font-weight: bold">真实排片销售额:</el-text>
</el-col>
<el-col :span="4" align="left">
<el-text>{{ realSales }}元</el-text>
</el-col>
</el-row>
<el-row>
<el-col :span="3" align="right">
<el-text style="font-weight: bold">智能排片耗时:</el-text>
</el-col>
<el-col :span="4" align="left">
<el-text>{{ takeTimes }}s</el-text>
</el-col>
</el-row>
<el-row>
<el-col :span="3" align="right">
<el-text style="font-weight: bold">智能排片消耗Tokens:</el-text>
</el-col>
<el-col :span="4" align="left">
<el-text>{{ tokens }}</el-text>
</el-col>
</el-row>
<el-row>
<el-col :span="3" align="right">
<el-text style="font-weight: bold">{{ compareDesc }}</el-text>
</el-col>
<el-col :span="9" align="left">
<el-text>{{ aiCount }}</el-text>
</el-col>
<el-col :span="9" align="left">
<el-text>{{ compareCount }}</el-text>
</el-col>
</el-row>
<el-row>
<el-col :span="3" align="right">
</el-col>
<el-col :span="9" align="left">
<el-text>{{ aiTotal }}</el-text>
</el-col>
<el-col :span="9" align="left">
<el-text>{{ compareTotal }}</el-text>
</el-col>
</el-row>
<el-row>
<el-col :span="3" align="right">
<el-text style="font-weight: bold">报告:</el-text>
</el-col>
<el-col :span="21" align="left">
<iframe :srcdoc="htmlView" style="width: 100%; height: 600px; border: 1px solid #ccc; border-radius: 20px"></iframe>
</el-col>
</el-row>
<el-row>
<el-col :span="3" align="right">
<el-text style="font-weight: bold">提示词版本:</el-text>
</el-col>
<el-col :span="21" align="left">
<el-text>{{ promptVersion }}</el-text>
</el-col>
</el-row>
<el-row>
<el-col :span="3" align="right">
<el-text style="font-weight: bold">提示词:</el-text>
</el-col>
<el-col :span="21" align="left">
<el-text>{{ prompt }}</el-text>
</el-col>
</el-row>
<el-row>
<el-col :span="3" align="right">
<el-text style="font-weight: bold">AI返回结果:</el-text>
</el-col>
<el-col :span="21" align="left">
<el-text>{{ showResult }}</el-text>
</el-col>
</el-row>
<el-row>
<el-col :span="3" align="right">
<el-text style="font-weight: bold">AI思考过程:</el-text>
</el-col>
<el-col :span="21" align="left">
<el-text>{{ think }}</el-text>
</el-col>
</el-row>
</template>
<style>
.el-text {
white-space: pre-wrap; /* 或者使用 pre-line */
}
.el-table .cell {
white-space: pre-line;
}
</style>

@ -1,240 +0,0 @@
<script setup>
import {onBeforeMount, onMounted, reactive, ref, unref, computed} from 'vue';
import {useStore, mapGetters, mapState} from "vuex";
import {cinema_list, cinema_search, cinema_user, change_cinema_user, write_git_version_to_db} from "@/apis/update.js";
import CinemaUpdate from "@/components/update/CinemaUpdate.vue";
// 注册vuex
const store = useStore()
// region 表单代码
// 搜索条件字段
const cinemaSearch = reactive({
ip: '',
version: '',
})
// 点击搜索时提交的数据
const cinemaSearchRef = ref()
// 数据校验部分 校验ip地址是否合法
const ip_validate = (rule, value, callback) => {
const regex = new RegExp('((2(5[0-5]|[0-4]\\d))|[0-1]?\\d{1,2})(\\.((2(5[0-5]|[0-4]\\d))|[0-1]?\\d{1,2})){3}');
if (value === '') {
callback()
}
if (!regex.test(value)) {
callback(new Error('请输入正确的IP地址'))
} else {
callback()
}
}
// 指定表单的校验规则, 仅对ip进行校验
const ipRule = reactive({
ip: [{validator: ip_validate, trigger: 'change'}]
})
// 数据提交 点击搜索按键提交数据
const submitSearch = async (formEl) => {
const {ip, version} = unref(cinemaSearch)
tableData.value = []
await cinema_search({ip, version}).then(
res => {
if (Array.isArray(res)) {
tableData.value = [...res]
} else {
}
}
).catch(
err => {
}
)
if (!formEl) return
formEl.validate((valid) => {
if (valid) {
console.log('提交数据')
} else {
console.log('提交失败')
return false
}
})
}
// 重置搜索数据的逻辑
const resetSearch = (formEl) => {
if (!formEl) return
formEl.resetFields()
}
// 刷新逻辑
const refresh = (formEL) => {
formEL.resetFields()
refresh_disable.value = true;
refresh_loading.value = true;
get_table_data()
update_git_version()
setTimeout(() => {
refresh_disable.value = false;
refresh_loading.value = false;
}, 5000)
}
// endregion
// region
const update_git_version = async () => {
await write_git_version_to_db().then(res => {
console.log(res)
}).catch(err => {
console.log(err)
}
)
}
// endregion
// region 表格数据代码
// 表格展示的数据
const tableData = ref([])
// 定义开关控制刷新按键的状态 disable和loading
let refresh_disable = ref(false)
let refresh_loading = ref(false)
// 通过异步请求获取影院列表数据
async function get_table_data() {
tableData.value = []
await cinema_list().then(res => {
if (Array.isArray(res)) {
tableData.value = [...res]
} else {
}
}).catch(err => {
console.log(err)
}
)
}
// 定义生命周期,在加载时获取一次表格数据
onMounted(
async () => {
await get_table_data();
}
)
// endregion
// region 常用人代码
// 定义常用人代码被选中的结果
const selectedUser = ref('')
// 定义变量用于接受返回数据
let userData = ref([])
// 定义用于展示的数据变量
onMounted(async () => {
await cinema_user().then((res) => {
const user_list = res.map((item, index) => {
return {key: item.id, label: item.username, value: item.username}
})
user_list.unshift({key: 0, label: '暂无', value: '暂无'})
userData.value = [...user_list]
}).catch((err) => {
})
})
const cinemaUserChange = (user, id) => {
const params = {user, id}
change_cinema_user(params).then(res => {
}).catch(err => {
})
}
// endregion
// region 升级相关代码
const update_ip = ref('')
const ver_id = ref(0)
const changeDialogStatus = (ip, ver) => {
store.state.updateModule.update_dialog_show = true
update_ip.value = ip
ver_id.value = ver
}
// endregion
</script>
<template>
<el-form
ref="cinemaSearchRef"
:model="cinemaSearch"
status-icon
:rules="ipRule"
class="cinema-search"
>
<el-row>
<el-col :span="5">
<el-form-item label="影院IP" prop="ip" label-width="60">
<el-input v-model="cinemaSearch.ip" placeholder="请输入完整的影院IP" style="width: 180px;"></el-input>
</el-form-item>
</el-col>
<el-col :span="5">
<el-form-item label="系统版本" prop="version">
<el-input v-model="cinemaSearch.version" placeholder="支持模糊查询" style="width: 160px;"></el-input>
</el-form-item>
</el-col>
<el-col :span="6">
<el-button type="primary" @click="submitSearch(cinemaSearchRef)">搜索</el-button>
<el-button @click="resetSearch(cinemaSearchRef)">重置</el-button>
<el-button v-bind:disabled="refresh_disable" @click="refresh(cinemaSearchRef)" v-bind:loading="refresh_loading">
刷新
</el-button>
</el-col>
</el-row>
</el-form>
<el-table :data="tableData" style="width: 100%">
<el-table-column prop="update_time" label="最后查询时间" min-width="180"></el-table-column>
<el-table-column prop="ip" label="操作" min-width="80">
<template v-slot="scope">
<el-button type="info" size="small" @click="changeDialogStatus(scope.row.ip, scope.row.ver_id)">更新</el-button>
</template>
</el-table-column>
<el-table-column prop="selectedUser" label="当前使用人" min-width="120">
<template v-slot="scope">
<el-select v-model="scope.row.user" class="m-2" size="small" laceholder="请选择" style="width: 80px"
@change="cinemaUserChange(scope.row.user, scope.row.id)">
<el-option v-for="data in userData" :key="data.id" :label="data.label"
:value="data.value"></el-option>
</el-select>
</template>
</el-table-column>
<el-table-column prop="name" label="影院名称" min-width="250"></el-table-column>
<el-table-column prop="ip" label="影院IP" min-width="120">
<template v-slot="scope">
<a target="_blank" style="color:#007bff;" v-if="scope.row.ip!=null"
v-bind:href="'http://'+scope.row.ip+'/?code=leying'">
{{ scope.row.ip }}
</a>
<span v-else> {{ scope.row.ip }}</span>
</template>
</el-table-column>
<el-table-column prop="zz_num" label="专资编码" min-width="100"></el-table-column>
<el-table-column prop="inner_id" label="鼎新编码" min-width="90"></el-table-column>
<el-table-column prop="sys_ver" label="系统版本" min-width="175"></el-table-column>
<el-table-column prop="client_ver" label="客户端版本" min-width="150"></el-table-column>
<el-table-column prop="is_cloud" label="云版本" min-width="80"></el-table-column>
<el-table-column prop="remote_label" label="远程办公识别码" min-width="160" class-name="remote"></el-table-column>
<el-table-column prop="db_user" label="数据库账号" min-width="100"></el-table-column>
<el-table-column prop="db_pwd" label="数据库密码" min-width="120"></el-table-column>
</el-table>
<CinemaUpdate :ip="update_ip" :ver_id="ver_id"></CinemaUpdate>
</template>
<style scoped>
:deep(td.remote div) {
font-family: "YaHei Consolas Hybrid";
}
</style>

@ -1,147 +0,0 @@
<script setup>
import {onBeforeMount, ref, computed} from 'vue';
import {get_group_data, get_group_func} from "@/apis/group.js";
// region 表格数据代码
const groupData = ref([])
// const tableData = ref([])
const dataSwitch = ref(false)
const update_time = ref('')
// 表头数据
const funcData = ref([])
const modelArray = ref([])
const groupFilter = ref([])
// const funcObj = ref({})
// 通过异步请求获取功能列表
async function get_func() {
funcData.value = []
await get_group_func().then(res => {
console.log(res)
funcData.value = [...res]
}).catch(err => {
console.log(err)
}
)
}
// 通过异步请求获取集团数据
async function get_data() {
tableData.value = []
await get_group_data().then(res => {
console.log(res)
if (res.status === 'success') {
update_time.value = res.data.update_datetime
groupData.value = [...res.data.groups_data]
console.log(groupData.value)
}
}).catch(err => {
console.log(err)
})
}
// 处理表格数据
const tableData = computed(() => {
const data = []
groupData.value.forEach(item => {
groupFilter.value.push({
'text': item['group_info']['group_name'] + '(' + item['group_info']['group_code'] + ')',
'value': item['group_info']['group_name'] + '(' + item['group_info']['group_code'] + ')'
})
let tempData = {
'group_info': item['group_info']['group_name'] + '(' + item['group_info']['group_code'] + ')',
'group_link': item['group_info']['group_address'],
'cinema_count': item['group_info']['cinema_count'],
}
item['group_data'].forEach(data => {
if (dataSwitch.value === false) {
tempData[data['func_id']] = data['data_count']
// tempData[data['func_id']] = {'data': data['data_count'], 'tips':data['data_lasttime']}
// tempData[data['func_id'] + '_data'] = data['data_count']
// tempData[data['func_id'] + '_tips'] = data['data_lasttime']
} else {
tempData[data['func_id']] = data['data_lasttime']
// tempData[data['func_id']] = {'data': data['data_lasttime'], 'tips':data['data_count']}
// tempData[data['func_id'] + '_data'] = data['data_lasttime']
// tempData[data['func_id'] + '_tips'] = data['data_count']
}
})
data.push(tempData)
})
console.log('tableData', data)
return data
})
const tableHeader = computed(() => {
let funcObj = {}
funcData.value.forEach(item => {
modelArray.value.push(item['func_model'])
if (funcObj.hasOwnProperty(item['func_model'])) {
funcObj[item['func_model']].push(item)
} else {
funcObj[item['func_model']] = [item]
}
})
console.log('funcObj', funcObj)
modelArray.value = [...new Set(modelArray.value)]
console.log('modelArray', modelArray.value)
return funcObj
})
const filterHandler = (value, row, column) => {
const property = column['property']
return row[property] === value
}
// 定义生命周期,在加载时获取一次表格数据
onBeforeMount(
async () => {
await get_func()
await get_data()
}
)
// endregion
</script>
<template>
<el-row align="middle" justify="end">
<el-col :span="2">
<el-text>数据更新时间:</el-text>
</el-col>
<el-col :span="3">
<el-text>{{ update_time }}</el-text>
</el-col>
<el-col :span="6">
<el-switch v-model="dataSwitch" active-text="数据最后更新时间" inactive-text="数据总条数" @change="get_data"/>
</el-col>
</el-row>
<el-table :data="tableData" max-height="700" :row-style="{ height: '68px' }"
empty-text='数据生成中,请等待3分钟后刷新!'>
<el-table-column prop="group_info" label="集团名称" min-width="200" fixed column-key="group_info" :filters="groupFilter" :filter-method="filterHandler"></el-table-column>
<el-table-column prop="cinema_count" label="集团影院数" min-width="120" sortable></el-table-column>
<el-table-column v-for="(func_array,model) in tableHeader" :label="model" align="center">
<el-table-column v-for="func in func_array" :prop="func['id']" :label="func['func_name']"
align="center" min-width="120" sortable>
</el-table-column>
</el-table-column>
</el-table>
</template>
<style>
.el-text {
white-space: pre-wrap; /* 或者使用 pre-line */
}
.el-table .cell {
white-space: pre-line;
}
</style>

@ -23,7 +23,7 @@ const checkAll = ref(false)
const isIndeterminate = ref(false)
const checkedMockConfig = ref([])
const mockConfigItems = ['download_film_info', 'get_cinema_info', 'get_screen_info', 'report_ticket',
'report_film_schedule', 'upload_screen_seat_info', 'report_check_ticket', 'get_overtime_ticket_status', 'valid_error']
'report_film_schedule', 'upload_screen_seat_info', 'get_overtime_ticket_status', 'valid_error']
const tabs_dict = [
{label: '影片信息下载', name: 'download_film_info'},
@ -32,7 +32,6 @@ const tabs_dict = [
{label: '票房数据上报', name: 'report_ticket'},
{label: '排片数据上报', name: 'report_film_schedule'},
{label: '座位信息上报', name: 'upload_screen_seat_info'},
{label: '检票数据上报', name: 'report_check_ticket'},
{label: '超时票务查询', name: 'get_overtime_ticket_status'},
{label: '数据清洗查询', name: 'valid_error'},
]
@ -70,8 +69,7 @@ const mockConfig =
label: '数据上报',
items: [{key: 'report_ticket', name: '票房数据上报接口'},
{key: 'report_film_schedule', name: '排片数据上报接口'},
{key: 'upload_screen_seat_info', name: '座位信息上报接口'},
{key: 'report_check_ticket', name: '检票数据上报接口'}]
{key: 'upload_screen_seat_info', name: '座位信息上报接口'}]
}, {
label: '超时票务审核',
items: [{key: 'get_overtime_ticket_status', name: '超时票务查询接口'},]
@ -243,13 +241,6 @@ function getResponseJson() {
console.log(err)
})
}
if (api === 'report_check_ticket') {
get_response_json(req).then(res => {
allJsonData.value.report_check_ticket = res
}).catch(err => {
console.log(err)
})
}
if (api === 'report_film_schedule') {
get_response_json(req).then(res => {
allJsonData.value.report_film_schedule = res
@ -336,7 +327,7 @@ const handleStart = () => {
alert('请先选择影院IP!')
return;
}
if (checkedMockConfig.value.length === 0) {
if (checkedMockConfig.value.length===0){
alert('请先选择要模拟的接口!')
return;
}
@ -428,7 +419,7 @@ onBeforeRouteLeave((from, to, next) => {
console.log(from.path)
if (to.path === '/mock' && running.value === true) {
alert('请先停止运行!')
} else {
}else{
next()
}

@ -1,343 +0,0 @@
<script setup>
import {onBeforeMount, onMounted, onBeforeUnmount, reactive, ref, unref, computed} from 'vue';
import {useStore, mapGetters, mapState} from "vuex";
import {
project_list,
prd_list,
prd_add,
prd_get,
prd_update,
prd_delete,
prd_history,
prd_list_ax_cloud
} from "@/apis/product.js";
import {storage} from "@/storage/storage.js";
import {onBeforeRouteLeave} from "vue-router";
// 注册vuex
const store = useStore()
// region 表单代码
// 点击搜索时提交的数据
const fromData = reactive({
project: '全部',
})
// region 表格数据代码
// 表格展示的数据
const tableData = ref([])
// 过滤条件数据
const projectList = ref([])
const currentPage = ref(1)
const pageSize = ref(15)
const total = ref(0)
const history_dialog_id = ref(1)
let local_storage_array = storage.get("prd_history")
// 处理翻页
const handleCurrentChange = (newPage) => {
currentPage.value = newPage
get_table_data(currentPage.value, pageSize.value, fromData.project)
}
const handleSizeChange = (newPageSize) => {
pageSize.value = newPageSize
get_table_data(currentPage.value, pageSize.value, fromData.project)
}
// 处理历史记录对话框
const changeDialogStatus = (id) => {
history_dialog_id.value = id
console.log('changeDialogStatus', id)
get_history(history_dialog_id.value)
}
// 定义数据源
const history_data = ref([])
// 定义对话框开关
let history_dialog_show = ref(false)
// 通过接口获取历史数据
function get_history(id) {
prd_history(id).then(res => {
console.log('get_history')
if (Array.isArray(res)) {
history_data.value = [...res]
}
history_dialog_show.value = true
}).catch(err => {
console.log(err)
});
}
const handleClose = () => {
history_dialog_show.value = false
history_data.value = []
}
// 数据提交 点击搜索按键提交数据
const submitSearch = async () => {
tableData.value = []
await get_table_data(currentPage.value, pageSize.value, fromData.project).then(
res => {
if (Array.isArray(res)) {
tableData.value = [...res]
} else {
}
}
).catch(
err => {
}
)
}
// 更新localstorage
function update_local_storage(id, update_at, update_mode = true) {
if (local_storage_array !== null) {
let find_local_data = false
local_storage_array.forEach((item) => {
if (item["id"] === id) {
if (update_mode === true) {
item["update_at"] = update_at
}
find_local_data = true
return true
}
})
if (!find_local_data) {
local_storage_array.push({id, update_at})
return true
}
return false
} else {
local_storage_array = new Array({id, update_at})
}
}
const update_table_data = (id) => {
tableData.value.forEach((item) => {
if (item.id === id) {
item.have_update = false
}
})
}
const mark_read = (id, update_at) => {
update_local_storage(id, update_at)
update_table_data(id)
save_local_storage()
}
const save_local_storage = () => {
tableData.value.forEach((table_item) => {
update_local_storage(table_item["id"], table_item["update_at"], false)
}
)
storage.remove('prd_history')
storage.set('prd_history', local_storage_array)
}
// 通过异步请求获取影院列表数据
async function get_project_data() {
projectList.value = []
await project_list().then(res => {
if (Array.isArray(res)) {
projectList.value = [...res]
projectList.value.unshift({'id': 0, 'project_name': '全部', is_delete: false})
} else {
}
}).catch(err => {
console.log(err)
}
)
}
// 通过异步请求获取影院列表数据
async function get_table_data(page_num = currentPage.value, page_size = pageSize.value, project_val = fromData.project) {
// 获取数据
tableData.value = []
console.log('get_table_data')
console.log(project_val)
project_val = project_val === '全部' ? '' : project_val
console.log(project_val)
await prd_list_ax_cloud(page_num, page_size, project_val).then(res => {
total.value = res['count']
if (Array.isArray(res['results'])) {
tableData.value = [...res['results']]
console.log(tableData.value)
} else {
console.log('get_table_data.res is not an array')
}
}).catch(err => {
console.log(err)
}
)
if (local_storage_array !== null) {
//处理新收到标记
tableData.value.forEach((table_item, table_index) => {
let find_local_data = false
table_item['have_update'] = false
local_storage_array.forEach((local_item, local_index) => {
if (table_item['id'] === local_item['id']) {
find_local_data = true
const table_datetime = new Date(table_item['update_at'])
const local_datetime = new Date(local_item['update_at'])
if (table_datetime > local_datetime) {
table_item['have_update'] = true
}
}
})
if (!find_local_data) {
table_item['have_update'] = true
}
})
}
}
// 定义生命周期,在加载时获取一次表格数据
onMounted(
async () => {
await get_project_data();
await get_table_data(currentPage.value, pageSize.value, fromData.project);
save_local_storage()
}
)
onBeforeUnmount(
() => {
save_local_storage()
}
)
onBeforeRouteLeave(
() => {
save_local_storage()
}
)
// endregion
</script>
<template>
<el-form
:model="fromData"
:inline="true"
class="search_form"
>
<el-form-item label="所属项目" label-width="90">
<el-select v-model="fromData.project" placeholder="请选择">
<el-option v-for="item in projectList" :key="item['project_name']" :label="item['project_name']"
:value="item['project_name']"/>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitSearch">搜索</el-button>
</el-form-item>
<!-- <el-button style="margin-right: 0">添加</el-button>-->
</el-form>
<el-table :data="tableData" style="width: 100%">
<el-table-column prop="project" label="所属项目" min-width="160"></el-table-column>
<el-table-column prop="prd_version" label="版本" min-width="160"></el-table-column>
<el-table-column prop="prd_status" label="版本状态" min-width="120"></el-table-column>
<el-table-column prop="prd_doc_link" label="产品原型链接" min-width="300" show-overflow-tooltip>
<template v-slot="scope">
<a target="_blank" style="color:#007bff;" v-if="scope.row.prd_doc_link!=null"
@click="mark_read(scope.row.id, scope.row.update_at)"
v-bind:href="scope.row.prd_doc_link">
{{
scope.row.prd_doc_link.length > 30 ? scope.row.prd_doc_link.slice(0, 30) + '...' : scope.row.prd_doc_link
}}
</a>
<sup v-if="scope.row.have_update"
style="color: red; margin-left: 3px; font-size: 10px">有更新</sup>
<!-- <span v-else> {{ scope.row.prd_doc_link }}</span>-->
</template>
</el-table-column>
<el-table-column prop="prd_comment" label="版本描述" min-width="260">
<template #default="{ row }">
<el-tooltip
class="item"
popper-class="custom-tooltip"
effect="dark"
:raw-content="true"
:content="row.prd_comment.split('\n').join('<br>')"
placement="top-end">
<span>{{ row.prd_comment.length > 10 ? row.prd_comment.slice(0, 10) + '...' : row.prd_comment }}</span>
</el-tooltip>
</template>
</el-table-column>
<el-table-column prop="update_at" label="最后更新时间" min-width="210">
</el-table-column>
<el-table-column prop="id" label="历史文档" min-width="120">
<template v-slot="scope">
<el-button type="primary" size="small" @click="changeDialogStatus(scope.row.id)"
:disabled="!scope.row.have_history">查看
</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination-container">
<el-pagination
v-model:current-page="currentPage"
v-model:page-size="pageSize"
:page-sizes="[15, 30, 50]"
size="small"
layout="sizes, prev, pager, next"
:total="total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
>
</el-pagination>
</div>
<template>
<el-dialog v-model="history_dialog_show" title="历史记录" width="500px" :modal="true"
:close-on-click-modal="false" :append-to-body="true" @close="handleClose">
<el-table :data="history_data" style="width: 100%">
<el-table-column prop="update_at" label="版本发布日期" min-width="100"></el-table-column>
<el-table-column prop="history_doc_link" label="产品原型链接" min-width="300" show-overflow-tooltip>
<template v-slot="scope">
<a target="_blank" style="color:#007bff;" v-if="scope.row.history_doc_link!=null"
v-bind:href="scope.row.history_doc_link">
{{
scope.row.history_doc_link.length > 30 ? scope.row.history_doc_link.slice(0, 30) + '...' : scope.row.history_doc_link
}}
</a>
</template>
</el-table-column>
</el-table>
</el-dialog>
</template>
</template>
<style>
.pagination-container {
display: flex;
justify-content: flex-end;
margin-top: 20px;
}
.search_form {
display: flex;
justify-content: flex-start;
}
.custom-tooltip {
max-width: 500px; /* 设置最大宽度为 300px */
}
</style>

@ -211,19 +211,13 @@ const changeDialogStatus = (ip, ver) => {
</template>
</el-table-column>
<el-table-column prop="name" label="影院名称" min-width="250"></el-table-column>
<el-table-column prop="url" label="影院地址" min-width="160">
<el-table-column prop="ip" label="影院IP" min-width="120">
<template v-slot="scope">
<a target="_blank" style="color:#007bff;" v-if="scope.row.url!=null"
v-bind:href="'http://'+scope.row.url+'/?code=leying'">
{{ scope.row.url }}
<a target="_blank" style="color:#007bff;" v-if="scope.row.ip!=null"
v-bind:href="'http://'+scope.row.ip+'/?code=leying'">
{{ scope.row.ip }}
</a>
<span v-else> {{ scope.row.url }}</span>
</template>
</el-table-column>
<el-table-column prop="is_online" label="状态" min-width="80">
<template v-slot="scope">
<span v-if="scope.row.is_online">正常</span>
<span style="color: red" v-if="!scope.row.is_online">异常</span>
<span v-else> {{ scope.row.ip }}</span>
</template>
</el-table-column>
<el-table-column prop="zz_num" label="专资编码" min-width="100"></el-table-column>
@ -234,12 +228,6 @@ const changeDialogStatus = (ip, ver) => {
<el-table-column prop="remote_label" label="远程办公识别码" min-width="160" class-name="remote"></el-table-column>
<el-table-column prop="db_user" label="数据库账号" min-width="100"></el-table-column>
<el-table-column prop="db_pwd" label="数据库密码" min-width="120"></el-table-column>
<el-table-column prop="comments" label="备注" min-width="200">
<template v-slot="scope">
<span v-if="scope.row.comments != null">{{ scope.row.comments }}</span>
<span v-else> -- </span>
</template>
</el-table-column>
</el-table>
<CinemaUpdate :ip="update_ip" :ver_id="ver_id"></CinemaUpdate>
</template>

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save